home *** CD-ROM | disk | FTP | other *** search
/ MacHome 2001 January / MacHome Magazine Demo Disc January 2001.iso / pc / Software / Applications / Squeak app design envir. ….sea / Squeak app design envir. 2.8 / SqueakV2.sources < prev   
Encoding:
Text File  |  1998-05-29  |  5.3 MB  |  164,029 lines  |  [STch/FAST]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. 'From Squeak 2.0 of May 22, 1998 on 22 May 1998 at 4:32:15 pm'!
  2. Object subclass: #AbstractScoreEvent
  3.     instanceVariableNames: 'time '
  4.     classVariableNames: ''
  5.     poolDictionaries: ''
  6.     category: 'Music-Scores'!
  7. !AbstractScoreEvent commentStamp: 'di 5/22/1998 16:32' prior: 0!
  8. Abstract class for timed events in a MIDI score.
  9. !
  10.  
  11.  
  12. !AbstractScoreEvent methodsFor: 'all' stamp: 'jm 12/31/97 11:46'!
  13. isNoteEvent
  14.  
  15.     ^ false
  16. ! !
  17.  
  18. !AbstractScoreEvent methodsFor: 'all' stamp: 'jm 12/31/97 11:46'!
  19. isTempoEvent
  20.  
  21.     ^ false
  22. ! !
  23.  
  24. !AbstractScoreEvent methodsFor: 'all' stamp: 'jm 12/31/97 11:43'!
  25. time
  26.  
  27.     ^ time
  28. ! !
  29.  
  30. !AbstractScoreEvent methodsFor: 'all' stamp: 'jm 12/31/97 11:43'!
  31. time: aNumber
  32.  
  33.     time _ aNumber.
  34. ! !
  35. Object subclass: #AbstractSound
  36.     instanceVariableNames: 'envelopes mSecsSinceStart samplesUntilNextControl scaledVol scaledVolIncr scaledVolLimit '
  37.     classVariableNames: 'MaxScaledValue ScaleFactor Sounds '
  38.     poolDictionaries: ''
  39.     category: 'System-Sound'!
  40.  
  41. !AbstractSound methodsFor: 'initialization' stamp: 'jm 12/9/97 11:31'!
  42. duration: seconds
  43.     "Scale my envelopes to the given duration. Subclasses overriding this method should include a resend to super."
  44.  
  45.     envelopes do: [:e | e duration: seconds].
  46. ! !
  47.  
  48. !AbstractSound methodsFor: 'initialization' stamp: 'jm 2/4/98 09:54'!
  49. initialize
  50.  
  51.     envelopes _ #().
  52.     mSecsSinceStart _ 0.
  53.     samplesUntilNextControl _ 0.
  54.     scaledVol _ (1.0 * ScaleFactor) rounded.
  55.     scaledVolIncr _ 0.
  56.     scaledVolLimit _ scaledVol.
  57. ! !
  58.  
  59. !AbstractSound methodsFor: 'initialization' stamp: 'jm 1/31/98 16:09'!
  60. setLoudness: vol
  61.     "Initialize my volume envelopes and initial volume. Subclasses overriding this method should include a resend to super."
  62.  
  63.     envelopes do: [:e |
  64.         (e isKindOf: VolumeEnvelope) ifTrue: [e scale: vol]].
  65.     self initialVolume: vol.
  66. ! !
  67.  
  68. !AbstractSound methodsFor: 'initialization' stamp: 'jm 1/31/98 15:26'!
  69. setPitch: p dur: d loudness: l
  70.     "Initialize my envelopes for the given parameters. Subclasses overriding this method should include a resend to super."
  71.  
  72.     envelopes do: [:e |
  73.         (e isKindOf: VolumeEnvelope) ifTrue: [e scale: l].
  74.         (e isKindOf: PitchEnvelope) ifTrue: [e centerPitch: p].
  75.         e duration: d].
  76.     self initialVolume: l.
  77.     self duration: d.
  78.  
  79. ! !
  80.  
  81.  
  82. !AbstractSound methodsFor: 'envelopes' stamp: 'jm 12/17/97 22:23'!
  83. addEnvelope: anEnvelope
  84.     "Add the given envelope to my envelopes list."
  85.  
  86.     anEnvelope target: self.
  87.     envelopes _ envelopes copyWith: anEnvelope.
  88. ! !
  89.  
  90. !AbstractSound methodsFor: 'envelopes' stamp: 'jm 12/15/97 17:02'!
  91. envelopes
  92.     "Return my collection of envelopes."
  93.  
  94.     ^ envelopes
  95. ! !
  96.  
  97. !AbstractSound methodsFor: 'envelopes' stamp: 'jm 12/15/97 17:02'!
  98. removeEnvelope: anEnvelope
  99.     "Remove the given envelope from my envelopes list."
  100.  
  101.     envelopes _ envelopes copyWithout: anEnvelope.
  102. ! !
  103.  
  104.  
  105. !AbstractSound methodsFor: 'volume' stamp: 'jm 2/4/98 06:49'!
  106. adjustVolumeTo: vol overMSecs: mSecs
  107.     "Adjust the volume of this sound to the given volume, a number in the range [0.0..1.0], over the given number of milliseconds. The volume will be changed a little bit on each sample until the desired volume is reached."
  108.  
  109.     | newScaledVol |
  110.     newScaledVol _ (32768.0 * vol) truncated.
  111.     newScaledVol = scaledVol ifTrue: [^ self].
  112.     scaledVolLimit _ newScaledVol.
  113.     scaledVolLimit > ScaleFactor ifTrue: [scaledVolLimit _ ScaleFactor].
  114.     scaledVolLimit < 0 ifTrue: [scaledVolLimit _ 0].
  115.     mSecs = 0
  116.         ifTrue: [  "change immediately"
  117.             scaledVol _ scaledVolLimit.
  118.             scaledVolIncr _ 0]
  119.         ifFalse: [
  120.             scaledVolIncr _
  121.                 ((scaledVolLimit - scaledVol) * 1000) // (self samplingRate * mSecs)].
  122. ! !
  123.  
  124. !AbstractSound methodsFor: 'volume' stamp: 'jm 12/17/97 17:39'!
  125. initialVolume: vol
  126.     "Set the initial volume of this sound to the given volume, a number in the range [0.0..1.0]."
  127.  
  128.     scaledVol _ (((vol asFloat min: 1.0) max: 0.0) * ScaleFactor) rounded.
  129.     scaledVolLimit _ scaledVol.
  130.     scaledVolIncr _ 0.
  131. ! !
  132.  
  133. !AbstractSound methodsFor: 'volume' stamp: 'di 1/31/98 15:55'!
  134. loudness
  135.     "Return a suitable volume for initing"
  136.  
  137.     ^ scaledVol asFloat / ScaleFactor asFloat! !
  138.  
  139. !AbstractSound methodsFor: 'volume' stamp: 'jm 12/16/97 10:30'!
  140. volumeEnvelopeScaledTo: scalePoint
  141.     "Return a collection of values representing my volume envelope scaled by the given point. The scale point's x component is pixels/second and its y component is the number of pixels for full volume."
  142.  
  143.     | env amp vScale cnt oldT newT totalCnt |
  144.     self error: 'not yet implemented'.
  145.  
  146. "old code:"
  147.     totalCnt _ "initialCount" 1000.
  148.     env _ Array new: (totalCnt * scalePoint x // self samplingRate min: 500).
  149.     amp _ scaledVol asFloat / ScaleFactor.
  150.     vScale _ scalePoint y asFloat / 1000.0.
  151.     cnt _ totalCnt.
  152.     oldT _ newT _ 0.  "Time in units of scale x per second"
  153.     [cnt > 0 and: [newT <= env size]] whileTrue:
  154.         [env atAll: (oldT+1 to: newT) put: (amp*vScale) asInteger.
  155.         oldT _ newT.
  156.         "amp _ amp * decayRate."
  157.         cnt _ cnt - samplesUntilNextControl.
  158.         newT _ totalCnt - cnt * scalePoint x // self samplingRate].
  159.     env atAll: ((oldT+1 min: env size) to: env size) put: (amp*vScale) asInteger.
  160.     ^ env
  161. ! !
  162.  
  163.  
  164. !AbstractSound methodsFor: 'playing' stamp: 'jm 1/26/98 22:05'!
  165. computeSamplesForSeconds: seconds
  166.     "Compute the samples of this sound without outputting them, and return the resulting buffer of samples."
  167.  
  168.     | buf |
  169.     self reset.
  170.     buf _ SoundBuffer newStereoSampleCount: (self samplingRate * seconds) asInteger.
  171.     self playSampleCount: buf stereoSampleCount into: buf startingAt: 1.
  172.     ^ buf
  173. ! !
  174.  
  175. !AbstractSound methodsFor: 'playing' stamp: 'jm 8/24/97 20:48'!
  176. pause
  177.     "Pause this sound. It can be resumed from this point, or reset and resumed to start from the beginning."
  178.  
  179.     SoundPlayer pauseSound: self.! !
  180.  
  181. !AbstractSound methodsFor: 'playing'!
  182. play
  183.     "Play this sound to the sound ouput port in real time."
  184.  
  185.     SoundPlayer playSound: self.! !
  186.  
  187. !AbstractSound methodsFor: 'playing' stamp: 'jm 12/9/97 10:46'!
  188. playAndWaitUntilDone
  189.     "Play this sound to the sound ouput port in real time."
  190.  
  191.     SoundPlayer playSound: self.
  192.     [self samplesRemaining > 0] whileTrue.
  193. ! !
  194.  
  195. !AbstractSound methodsFor: 'playing' stamp: 'jm 1/26/98 22:05'!
  196. playSampleCount: n into: aSoundBuffer startingAt: startIndex
  197.     "Mixes the next count samples of this sound into the given buffer starting at the given index, updating the receiver's control parameters at periodic intervals."
  198.  
  199.     | fullVol samplesBetweenControlUpdates pastEnd i remainingSamples count |
  200.     fullVol _ AbstractSound scaleFactor.
  201.     samplesBetweenControlUpdates _ self samplingRate // self controlRate.
  202.     pastEnd _ startIndex + n.  "index just index of after last sample"
  203.     i _ startIndex.
  204.     [i < pastEnd] whileTrue: [
  205.         remainingSamples _ self samplesRemaining.
  206.         remainingSamples <= 0 ifTrue: [^ self].
  207.         count _ pastEnd - i.
  208.         samplesUntilNextControl < count ifTrue: [count _ samplesUntilNextControl].
  209.         remainingSamples < count ifTrue: [count _ remainingSamples].
  210.         self mixSampleCount: count into: aSoundBuffer startingAt: i leftVol: fullVol rightVol: fullVol.
  211.         samplesUntilNextControl _ samplesUntilNextControl - count.
  212.         samplesUntilNextControl <= 0 ifTrue: [
  213.             self doControl.
  214.             samplesUntilNextControl _ samplesBetweenControlUpdates].
  215.         i _ i + count].
  216. ! !
  217.  
  218. !AbstractSound methodsFor: 'playing' stamp: 'jm 1/26/98 22:05'!
  219. playSilently
  220.     "Compute the samples of this sound without outputting them. Used for performance analysis."
  221.  
  222.     | buf |
  223.     self reset.
  224.     buf _ SoundBuffer newStereoSampleCount: (self samplingRate // 10).
  225.     [self samplesRemaining > 0] whileTrue: [
  226.         buf primFill: 0.
  227.         self playSampleCount: buf stereoSampleCount into: buf startingAt: 1].
  228. ! !
  229.  
  230. !AbstractSound methodsFor: 'playing' stamp: 'jm 1/26/98 22:06'!
  231. playSilentlyUntil: startTime
  232.     "Compute the samples of this sound without outputting them. Used to fast foward to a particular starting time. The start time is given in seconds."
  233.  
  234.     | buf startSample nextSample samplesRemaining n |
  235.     self reset.
  236.     buf _ SoundBuffer newStereoSampleCount: (self samplingRate // 10).
  237.     startSample _ (startTime * self samplingRate) asInteger.
  238.     nextSample _ 1.
  239.     [self samplesRemaining > 0] whileTrue: [
  240.         nextSample >= startSample ifTrue: [^ self].
  241.         samplesRemaining _ startSample - nextSample.
  242.         samplesRemaining > buf stereoSampleCount
  243.             ifTrue: [n _ buf stereoSampleCount]
  244.             ifFalse: [n _ samplesRemaining].
  245.         self playSampleCount: n into: buf startingAt: 1.
  246.         nextSample _ nextSample + n].
  247. ! !
  248.  
  249. !AbstractSound methodsFor: 'playing' stamp: 'jm 3/4/98 13:16'!
  250. resumePlaying
  251.     "Resume playing this sound from where it last stopped."
  252.  
  253.     SoundPlayer resumePlaying: self.
  254. ! !
  255.  
  256.  
  257. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 2/4/98 09:56'!
  258. doControl
  259.     "Update the control parameters of this sound using its envelopes, if any."
  260.     "Note: This is only called at a small fraction of the sampling rate."
  261.  
  262.     | pitchModOrRatioChange |
  263.     mSecsSinceStart _ mSecsSinceStart + (1000 // self controlRate).
  264.     envelopes size > 0 ifTrue: [
  265.         pitchModOrRatioChange _ false.
  266.         1 to: envelopes size do: [:i |
  267.             ((envelopes at: i) updateTargetAt: mSecsSinceStart)
  268.                 ifTrue: [pitchModOrRatioChange _ true]].
  269.         pitchModOrRatioChange ifTrue: [self internalizeModulationAndRatio]].
  270. ! !
  271.  
  272. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 2/4/98 08:56'!
  273. internalizeModulationAndRatio
  274.     "Overridden by FMSound. This default implementation does nothing."
  275. ! !
  276.  
  277. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 11/24/97 16:00'!
  278. mixSampleCount: n into: aSoundBuffer startingAt: startIndex leftVol: leftVol rightVol: rightVol
  279.     "Mix the given number of samples with the samples already in the given buffer starting at the given index. Assume that the buffer size is at least (index + count) - 1. The leftVol and rightVol parameters determine the volume of the sound in each channel, where 0 is silence and 1000 is full volume."
  280.  
  281.     self subclassResponsibility.
  282. ! !
  283.  
  284. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 2/4/98 18:59'!
  285. reset
  286.     "Reset my internal state for a replay. Methods that override this method should do super reset."
  287.  
  288.     mSecsSinceStart _ 0.
  289.     samplesUntilNextControl _ self samplingRate // self controlRate.
  290.     envelopes size > 0 ifTrue: [
  291.         1 to: envelopes size do: [:i | (envelopes at: i) reset]].
  292. ! !
  293.  
  294. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 12/17/97 17:57'!
  295. samplesRemaining
  296.     "Answer the number of samples remaining until the end of this sound. A sound with an indefinite ending time should answer some large integer such as 1000000."
  297.  
  298.     ^ 1000000
  299. ! !
  300.  
  301. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 1/5/98 14:21'!
  302. storeSample: sample in: aSoundBuffer at: sliceIndex leftVol: leftVol rightVol: rightVol
  303.     "This method is provided for documentation. To gain 10% more speed when running sound generation in Smalltalk, this method is hand-inlined into all sound generation methods that use it."
  304.  
  305.     | i s |
  306.         leftVol > 0 ifTrue: [
  307.             i _ (2 * sliceIndex) - 1.
  308.             s _ (aSoundBuffer at: i) + ((sample * leftVol) // ScaleFactor).
  309.             s >  32767 ifTrue: [s _  32767].  "clipping!!"
  310.             s < -32767 ifTrue: [s _ -32767].  "clipping!!"
  311.             aSoundBuffer at: i put: s].
  312.         rightVol > 0 ifTrue: [
  313.             i _ 2 * sliceIndex.
  314.             s _ (aSoundBuffer at: i) + ((sample * rightVol) // ScaleFactor).
  315.             s >  32767 ifTrue: [s _  32767].  "clipping!!"
  316.             s < -32767 ifTrue: [s _ -32767].  "clipping!!"
  317.             aSoundBuffer at: i put: s].
  318. ! !
  319.  
  320. !AbstractSound methodsFor: 'sound generation' stamp: 'jm 12/17/97 17:57'!
  321. updateVolume
  322.     "Increment the volume envelope of this sound. To avoid clicks, the volume envelope must be interpolated at the sampling rate, rather than just at the control rate like other envelopes. At the control rate, the volume envelope computes the slope and next target volume volume for the current segment of the envelope (i.e., it sets the rate of change for the volume parameter). When that target volume is reached, incrementing is stopped until a new increment is set."
  323.     "This method is provided for documentation. To gain 10% more speed when running sound generation in Smalltalk, it is hand-inlined into all sound generation methods that use it."
  324.  
  325.         scaledVolIncr ~= 0 ifTrue: [
  326.             scaledVol _ scaledVol + scaledVolIncr.
  327.             ((scaledVolIncr > 0 and: [scaledVol >= scaledVolLimit]) or:
  328.              [scaledVolIncr < 0 and: [scaledVol <= scaledVolLimit]])
  329.                 ifTrue: [  "reached the limit; stop incrementing"
  330.                     scaledVol _ scaledVolLimit.
  331.                     scaledVolIncr _ 0]].
  332. ! !
  333.  
  334.  
  335. !AbstractSound methodsFor: 'composition'!
  336. + aSound
  337.     "Return the mix of the receiver and the argument sound."
  338.  
  339.     ^ MixedSound new
  340.         add: self;
  341.         add: aSound
  342. ! !
  343.  
  344. !AbstractSound methodsFor: 'composition'!
  345. , aSound
  346.     "Return the concatenation of the receiver and the argument sound."
  347.  
  348.     ^ SequentialSound new
  349.         add: self;
  350.         add: aSound
  351. ! !
  352.  
  353. !AbstractSound methodsFor: 'composition' stamp: 'jm 12/17/97 18:00'!
  354. delayedBy: seconds
  355.     "Return a composite sound consisting of a rest for the given amount of time followed by the receiver."
  356.  
  357.     ^ (RestSound dur: seconds), self
  358. ! !
  359.  
  360.  
  361. !AbstractSound methodsFor: 'sampling rates' stamp: 'jm 12/15/97 14:15'!
  362. controlRate
  363.     "Answer the number of control changes per second."
  364.  
  365.     ^ 100
  366. ! !
  367.  
  368. !AbstractSound methodsFor: 'sampling rates' stamp: 'jm 12/17/97 18:00'!
  369. samplingRate
  370.     "Answer the sampling rate in samples per second."
  371.  
  372.     ^ SoundPlayer samplingRate
  373. ! !
  374.  
  375.  
  376. !AbstractSound methodsFor: 'copying' stamp: 'jm 12/15/97 19:15'!
  377. copy
  378.     "A sound should copy all of the state needed to play itself, allowing two copies of a sound to play at the same time. These semantics require a recursive copy but only down to the level of immutable data. For example, a SampledSound need not copy its sample buffer. Subclasses overriding this method should include a resend to super."
  379.  
  380.     ^ self clone copyEnvelopes
  381. ! !
  382.  
  383. !AbstractSound methodsFor: 'copying' stamp: 'jm 12/17/97 22:22'!
  384. copyEnvelopes
  385.     "Private!! Support for copying. Copy my envelopes."
  386.  
  387.     envelopes _ envelopes collect: [:e | e copy target: self].
  388. ! !
  389.  
  390. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  391.  
  392. AbstractSound class
  393.     instanceVariableNames: ''!
  394.  
  395. !AbstractSound class methodsFor: 'class initialization' stamp: 'di 2/2/98 14:39'!
  396. initialize
  397.     "AbstractSound initialize"
  398.  
  399.     ScaleFactor _ 2 raisedTo: 15.
  400.     MaxScaledValue _ ((2 raisedTo: 31) // ScaleFactor) - 1.  "magnitude of largest scaled value in 32-bits"! !
  401.  
  402. !AbstractSound class methodsFor: 'class initialization' stamp: 'jm 1/5/98 13:51'!
  403. scaleFactor
  404.  
  405.     ^ ScaleFactor
  406. ! !
  407.  
  408.  
  409. !AbstractSound class methodsFor: 'instance creation' stamp: 'jm 1/5/98 17:40'!
  410. default
  411.     "Return a default sound prototype for this class, with envelopes if appropriate. (This is in contrast to new, which returns a raw instance without envelopes.)"
  412.  
  413.     ^ self new
  414. ! !
  415.  
  416. !AbstractSound class methodsFor: 'instance creation' stamp: 'jm 12/17/97 17:26'!
  417. dur: d
  418.     "Return a rest of the given duration."
  419.  
  420.     ^ self basicNew setDur: d
  421. ! !
  422.  
  423. !AbstractSound class methodsFor: 'instance creation' stamp: 'jm 12/17/97 17:26'!
  424. new
  425.  
  426.     ^ self basicNew initialize
  427. ! !
  428.  
  429. !AbstractSound class methodsFor: 'instance creation' stamp: 'di 1/30/98 14:28'!
  430. noteSequenceOn: aSound from: anArray
  431.     "Build a note sequence (i.e., a SequentialSound) from the given array using the given sound as the instrument. Elements are either (pitch, duration, loudness) triples or (#rest duration) pairs.  Pitches can be given as names or as numbers."
  432.     | score pitch |
  433.     score _ SequentialSound new.
  434.     anArray do: [:el |
  435.         el size = 3
  436.             ifTrue: [
  437.                 pitch _ el at: 1.
  438.                 pitch isNumber ifFalse: [pitch _ self pitchForName: pitch].
  439.                 score add: (
  440.                     aSound copy
  441.                         setPitch: pitch
  442.                         dur: (el at: 2)
  443.                         loudness: (el at: 3) / 1000.0)]
  444.             ifFalse: [
  445.                 score add: (RestSound dur: (el at: 2))]].
  446.     ^ score
  447. ! !
  448.  
  449. !AbstractSound class methodsFor: 'instance creation' stamp: 'jm 12/17/97 17:27'!
  450. pitch: p dur: d loudness: l
  451.     "Return a new sound object for a note with the given parameters."
  452.  
  453.     ^ self new setPitch: p dur: d loudness: l
  454. ! !
  455.  
  456. !AbstractSound class methodsFor: 'instance creation'!
  457. pitchForName: aString
  458.     "AbstractSound pitchForName: 'c2'"
  459.     "#(c 'c#' d eb e f fs g 'g#' a bf b) collect: [ :s | AbstractSound pitchForName: s, '4']"
  460.  
  461.     | s modifier octave i j noteName p |
  462.     s _ ReadStream on: aString.
  463.     modifier _ $n.
  464.     noteName _ s next.
  465.     (s atEnd not and: [s peek isDigit]) ifFalse: [ modifier _ s next ].
  466.     s atEnd
  467.         ifTrue: [ octave _ 4 ]
  468.         ifFalse: [ octave _ Integer readFrom: s ].
  469.     octave < 0 ifTrue: [ self error: 'cannot use negative octave number' ].
  470.     i _ 'cdefgab' indexOf: noteName.
  471.     i = 0 ifTrue: [ self error: 'bad note name: ', noteName asString ].
  472.     i _ #(2 4 6 7 9 11 13) at: i.
  473.     j _ 's#fb' indexOf: modifier.
  474.     j = 0 ifFalse: [ i _ i + (#(1 1 -1 -1) at: j) ].  "i is now in range: [1..14]"
  475.     "Table generator: (1 to: 14) collect: [ :i | 16.3516 * (2.0 raisedTo: (i - 2) asFloat / 12.0)]"
  476.     p _ #(15.4339 16.3516 17.3239 18.354 19.4454 20.6017 21.8268 23.1247 24.4997 25.9565 27.5 29.1352 30.8677 32.7032) at: i.
  477.     octave timesRepeat: [ p _ 2.0 * p ].
  478.     ^ p
  479. ! !
  480.  
  481.  
  482. !AbstractSound class methodsFor: 'examples' stamp: 'di 1/31/98 00:33'!
  483. chromaticPitchesFrom: aPitch
  484.     | pitch halfStep |
  485.     pitch _ aPitch isNumber
  486.             ifTrue: [aPitch]
  487.             ifFalse: [self pitchForName: aPitch].
  488.     halfStep _ self halfStep.
  489.     pitch _ pitch / halfStep.
  490.     ^ (0 to: 14) collect: [:i | pitch _ pitch * halfStep]! !
  491.  
  492. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/5/98 17:35'!
  493. chromaticScale
  494.     "PluckedSound chromaticScale play"
  495.  
  496.     ^ self chromaticScaleOn: self default
  497. ! !
  498.  
  499. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/31/98 16:14'!
  500. chromaticScaleOn: aSound
  501.     "PluckedSound chromaticScale play"
  502.  
  503.     ^ self noteSequenceOn: aSound
  504.         from: (((self chromaticPitchesFrom: #c4) copyFrom: 1 to: 13)
  505.              collect: [:pitch | Array with: pitch with: 0.5 with: 300])
  506. ! !
  507.  
  508. !AbstractSound class methodsFor: 'examples' stamp: 'di 1/31/98 00:32'!
  509. halfStep
  510.     ^ 2.0 raisedTo: 1.0/12.0! !
  511.  
  512. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/5/98 17:36'!
  513. hiMajorScale
  514.     "FMSound hiMajorScale play"
  515.  
  516.     ^ self hiMajorScaleOn: self default
  517. ! !
  518.  
  519. !AbstractSound class methodsFor: 'examples' stamp: 'di 1/30/98 16:00'!
  520. hiMajorScaleOn: aSound
  521.     "FMSound hiMajorScale play"
  522.  
  523.     ^ self majorScaleOn: aSound from: #c6! !
  524.  
  525. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/5/98 17:36'!
  526. lowMajorScale
  527.     "PluckedSound lowMajorScale play"
  528.  
  529.     ^ self lowMajorScaleOn: self default
  530. ! !
  531.  
  532. !AbstractSound class methodsFor: 'examples' stamp: 'di 1/30/98 16:01'!
  533. lowMajorScaleOn: aSound
  534.     "PluckedSound lowMajorScale play"
  535.  
  536.     ^ self majorScaleOn: aSound from: #c3! !
  537.  
  538. !AbstractSound class methodsFor: 'examples' stamp: 'di 1/30/98 16:04'!
  539. majorChord
  540.     "FMSound majorChord play"
  541.     ^ self majorChordOn: self default from: #c4! !
  542.  
  543. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/31/98 16:25'!
  544. majorChordOn: aSound from: aPitch
  545.     "FMSound majorChord play"
  546.     | score majorScale leadingRest pan note |
  547.     majorScale _ self majorPitchesFrom: aPitch.
  548.     score _ MixedSound new.
  549.     leadingRest _ pan _ 0.
  550.     #(1 3 5 8) do: [:noteIndex |
  551.         note _ aSound copy
  552.             setPitch: (majorScale at: noteIndex)
  553.             dur: 2.0 - leadingRest
  554.             loudness: 0.3.
  555.         score add: (RestSound dur: leadingRest), note pan: pan.
  556.         leadingRest _ leadingRest + 0.2.
  557.         pan _ pan + 0.3].
  558.     ^ score
  559. ! !
  560.  
  561. !AbstractSound class methodsFor: 'examples' stamp: 'di 1/30/98 14:45'!
  562. majorPitchesFrom: aPitch
  563.     | chromatic |
  564.     chromatic _ self chromaticPitchesFrom: aPitch.
  565.     ^ #(1 3 5 6 8 10 12 13 15 13 12 10 8 6 5 3 1) collect: [:i | chromatic at: i].
  566. ! !
  567.  
  568. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/5/98 17:34'!
  569. majorScale
  570.     "FMSound majorScale play"
  571.  
  572.     ^ self majorScaleOn: self default
  573. ! !
  574.  
  575. !AbstractSound class methodsFor: 'examples' stamp: 'di 1/30/98 16:00'!
  576. majorScaleOn: aSound
  577.     "FMSound majorScale play"
  578.  
  579.     ^ self majorScaleOn: aSound from: #c5! !
  580.  
  581. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/31/98 16:14'!
  582. majorScaleOn: aSound from: aPitch
  583.     "FMSound majorScale play"
  584.  
  585.     ^ self noteSequenceOn: aSound
  586.         from: ((self majorPitchesFrom: aPitch)
  587.              collect: [:pitch | Array with: pitch with: 0.25 with: 300])
  588. ! !
  589.  
  590. !AbstractSound class methodsFor: 'examples' stamp: 'jm 1/5/98 17:32'!
  591. scaleTest
  592.     "AbstractSound scaleTest play"
  593.  
  594.     ^ MixedSound new
  595.         add: FMSound majorScale pan: 0;
  596.         add: (PluckedSound lowMajorScale delayedBy: 0.5) pan: 1.0.
  597. ! !
  598.  
  599. !AbstractSound class methodsFor: 'examples' stamp: 'jm 12/17/97 21:25'!
  600. testFMInteractively
  601.     "Experiment with different settings of the FM modulation and multiplier settings interactively by moving the mouse. The top-left corner of the screen is 0 for both parameters. Stop when the mouse is pressed."
  602.     "AbstractSound testFMInteractively"
  603.  
  604.     | s mousePt lastVal status mod mult |
  605.     SoundPlayer startPlayerProcessBufferSize: 1100 rate: 11025 stereo: false.
  606.     s _ FMSound pitch: 440.0 dur: 200.0 loudness: 0.2.
  607.  
  608.     SoundPlayer playSound: s.
  609.     lastVal _ nil.
  610.     [Sensor anyButtonPressed] whileFalse: [
  611.         mousePt _ Sensor cursorPoint.
  612.         mousePt ~= lastVal ifTrue: [
  613.             mod _ mousePt x asFloat / 20.0.
  614.             mult _ mousePt y asFloat / 20.0.
  615.             s modulation: mod multiplier: mult.
  616.             lastVal _ mousePt.
  617.             status _
  618. 'mod: ', mod printString, '
  619. mult: ', mult printString.
  620.             status asParagraph displayOn: Display at: 10@10]].
  621.  
  622.     SoundPlayer shutDown.
  623. ! !
  624.  
  625.  
  626. !AbstractSound class methodsFor: 'examples-bach fugue' stamp: 'jm 1/5/98 17:38'!
  627. bachFugue
  628.     "Play a fugue by J. S. Bach using and instance of me as the sound for all four voices."
  629.     "PluckedSound bachFugue play"
  630.  
  631.     ^ self bachFugueOn: self default
  632. ! !
  633.  
  634. !AbstractSound class methodsFor: 'examples-bach fugue' stamp: 'jm 1/5/98 18:27'!
  635. bachFugueOn: aSound
  636.     "Play a fugue by J. S. Bach using the given sound as the sound for all four voices."
  637.     "PluckedSound bachFugue play"
  638.  
  639.     ^ MixedSound new
  640.         add: (self bachFugueVoice1On: aSound) pan: 1.0;
  641.         add: (self bachFugueVoice2On: aSound) pan: 0.0;
  642.         add: (self bachFugueVoice3On: aSound) pan: 1.0;
  643.         add: (self bachFugueVoice4On: aSound) pan: 0.0.
  644. ! !
  645.  
  646. !AbstractSound class methodsFor: 'examples-bach fugue' stamp: 'jm 12/17/97 16:51'!
  647. bachFugueVoice1On: aSound
  648.     "Voice one of a fugue by J. S. Bach."
  649.  
  650.     ^ self noteSequenceOn: aSound from: #(
  651.         (1047 0.15 268)
  652.         (988  0.15 268)
  653.         (1047 0.30 268)
  654.         (784  0.30 268)
  655.         (831  0.30 268)
  656.         (1047 0.15 268)
  657.         (988  0.15 268)
  658.         (1047 0.30 268)
  659.         (1175 0.30 268)
  660.         (784  0.30 268)
  661.         (1047 0.15 268)
  662.         (988  0.15 268)
  663.         (1047 0.30 268)
  664.         (1175 0.30 268)
  665.         (698  0.15 268)
  666.         (784  0.15 268)
  667.         (831  0.60 268)
  668.         (784  0.15 268)
  669.         (698  0.15 268)
  670.         (622  0.15 268)
  671.         (1047 0.15 268)
  672.         (988  0.15 268)
  673.         (880  0.15 268)
  674.         (784  0.15 268)
  675.         (698  0.15 268)
  676.         (622  0.15 268)
  677.         (587  0.15 268)
  678.         (523  0.30 268)
  679.         (1245 0.30 268)
  680.         (1175 0.30 268)
  681.         (1047 0.30 268)
  682.         (932  0.30 268)
  683.         (880  0.30 268)
  684.         (932  0.30 268)
  685.         (1047 0.30 268)
  686.         (740  0.30 268)
  687.         (784  0.30 268)
  688.         (880  0.30 268)
  689.         (740  0.30 268)
  690.         (784  0.60 268)
  691.         (rest 0.15)
  692.         (523  0.15 268)
  693.         (587  0.15 268)
  694.         (622  0.15 268)
  695.         (698  0.15 268)
  696.         (784  0.15 268)
  697.         (831  0.45 268)
  698.         (587  0.15 268)
  699.         (622  0.15 268)
  700.         (698  0.15 268)
  701.         (784  0.15 268)
  702.         (880  0.15 268)
  703.         (932  0.45 268)
  704.         (622  0.15 268)
  705.         (698  0.15 268)
  706.         (784  0.15 268)
  707.         (831  0.15 268)
  708.         (784  0.15 268)
  709.         (698  0.15 268)
  710.         (622  0.15 268)
  711.         (587  0.30 268)
  712.         (1047 0.15 268)
  713.         (988  0.15 268)
  714.         (1047 0.60 268)
  715.         (rest 0.9)
  716.         (1397 0.30 268)
  717.         (1245 0.30 268)
  718.         (1175 0.30 268)
  719.         (rest 0.3)
  720.         (831  0.30 268)
  721.         (784  0.30 268)
  722.         (698  0.30 268)
  723.         (784  0.30 268)
  724.         (698  0.15 268)
  725.         (622  0.15 268)
  726.         (698  0.30 268)
  727.         (587  0.30 268)
  728.         (784  0.60 268)
  729.         (rest 0.3)
  730.         (988  0.30 268)
  731.         (1047 0.30 268)
  732.         (1047 0.15 268)
  733.         (988  0.15 268)
  734.         (1047 0.30 268)
  735.         (784  0.30 268)
  736.         (831  0.60 268)
  737.         (rest 0.3)
  738.         (880  0.30 268)
  739.         (932  0.30 268)
  740.         (932  0.15 268)
  741.         (880  0.15 268)
  742.         (932  0.30 268)
  743.         (698  0.30 268)
  744.         (784  0.60 268)
  745.         (rest 0.3)
  746.         (784  0.30 268)
  747.         (831  0.30 268)
  748.         (831  0.30 268)
  749.         (784  0.30 268)
  750.         (698  0.30 268)
  751.         (rest 0.3)
  752.         (415  0.30 268)
  753.         (466  0.30 268)
  754.         (523  0.30 268)
  755.         (rest 0.3)
  756.         (415  0.15 268)
  757.         (392  0.15 268)
  758.         (415  0.30 268)
  759.         (349  0.30 268)
  760.         (466  0.30 268)
  761.         (523  0.30 268)
  762.         (466  0.30 268)
  763.         (415  0.30 268)
  764.         (466  0.30 268)
  765.         (392  0.30 268)
  766.         (349  0.30 268)
  767.         (311  0.30 268)
  768.         (349  0.30 268)
  769.         (554  0.30 268)
  770.         (523  0.30 268)
  771.         (466  0.30 268)
  772.         (523  0.30 268)
  773.         (415  0.30 268)
  774.         (392  0.30 268)
  775.         (349  0.30 268)
  776.         (392  0.30 268)
  777.         (784  0.15 268)
  778.         (740  0.15 268)
  779.         (784  0.30 268)
  780.         (523  0.30 268)
  781.         (622  0.30 268)
  782.         (784  0.15 268)
  783.         (740  0.15 268)
  784.         (784  0.30 268)
  785.         (880  0.30 268)
  786.         (587  0.30 268)
  787.         (784  0.15 268)
  788.         (740  0.15 268)
  789.         (784  0.30 268)
  790.         (880  0.30 268)
  791.         (523  0.15 268)
  792.         (587  0.15 268)
  793.         (622  0.60 268)
  794.         (587  0.15 268)
  795.         (523  0.15 268)
  796.         (466  0.30 346)
  797.         (rest 0.45)
  798.         (587  0.15 346)
  799.         (659  0.15 346)
  800.         (740  0.15 346)
  801.         (784  0.15 346)
  802.         (880  0.15 346)
  803.         (932  0.45 346)
  804.         (659  0.15 346)
  805.         (698  0.15 346)
  806.         (784  0.15 346)
  807.         (880  0.15 346)
  808.         (932  0.15 346)
  809.         (1047 0.45 346)
  810.         (740  0.15 346)
  811.         (784  0.15 346)
  812.         (880  0.15 346)
  813.         (932  0.30 346)
  814.         (622  0.15 346)
  815.         (587  0.15 346)
  816.         (622  0.30 346)
  817.         (392  0.30 346)
  818.         (415  0.30 346)
  819.         (698  0.15 346)
  820.         (622  0.15 346)
  821.         (698  0.30 346)
  822.         (440  0.30 346)
  823.         (466  0.30 346)
  824.         (784  0.15 346)
  825.         (698  0.15 346)
  826.         (784  0.30 346)
  827.         (494  0.30 346)
  828.         (523  0.15 346)
  829.         (698  0.15 346)
  830.         (622  0.15 346)
  831.         (587  0.15 346)
  832.         (523  0.15 346)
  833.         (466  0.15 346)
  834.         (440  0.15 346)
  835.         (392  0.15 346)
  836.         (349  0.30 346)
  837.         (831  0.30 346)
  838.         (784  0.30 346)
  839.         (698  0.30 346)
  840.         (622  0.30 346)
  841.         (587  0.30 346)
  842.         (622  0.30 346)
  843.         (698  0.30 346)
  844.         (494  0.30 346)
  845.         (523  0.30 346)
  846.         (587  0.30 346)
  847.         (494  0.30 346)
  848.         (523  0.60 346)
  849.         (rest 0.3)
  850.         (659  0.30 346)
  851.         (698  0.30 346)
  852.         (698  0.15 346)
  853.         (659  0.15 346)
  854.         (698  0.30 346)
  855.         (523  0.30 346)
  856.         (587  0.60 346)
  857.         (rest 0.3)
  858.         (587  0.30 346)
  859.         (622  0.30 346)
  860.         (622  0.15 346)
  861.         (587  0.15 346)
  862.         (622  0.30 346)
  863.         (466  0.30 346)
  864.         (523  1.20 346)
  865.         (523  0.30 346)
  866.         (587  0.15 346)
  867.         (622  0.15 346)
  868.         (698  0.15 346)
  869.         (622  0.15 346)
  870.         (698  0.15 346)
  871.         (587  0.15 346)
  872.         (494  0.30 457)
  873.         (rest 0.6)
  874.         (494  0.30 457)
  875.         (523  0.30 457)
  876.         (rest 0.6)
  877.         (622  0.30 457)
  878.         (587  0.30 457)
  879.         (rest 0.6)
  880.         (698  0.60 457)
  881.         (rest 0.6)
  882.         (698  0.30 457)
  883.         (622  0.30 457)
  884.         (831  0.30 457)
  885.         (784  0.30 457)
  886.         (698  0.30 457)
  887.         (622  0.30 457)
  888.         (587  0.30 457)
  889.         (622  0.30 457)
  890.         (698  0.30 457)
  891.         (494  0.30 457)
  892.         (523  0.30 457)
  893.         (587  0.30 457)
  894.         (494  0.30 457)
  895.         (494  0.30 457)
  896.         (523  0.30 457)
  897.         (rest 0.3)
  898.         (523  0.30 457)
  899.         (698  0.15 457)
  900.         (587  0.15 457)
  901.         (622  0.15 457)
  902.         (523  0.45 457)
  903.         (494  0.30 457)
  904.         (523  0.60 457)
  905.         (rest 0.3)
  906.         (659  0.30 268)
  907.         (698  0.60 268)
  908.         (rest 0.3)
  909.         (698  0.30 268)
  910.         (698  0.30 268)
  911.         (622  0.15 268)
  912.         (587  0.15 268)
  913.         (622  0.30 268)
  914.         (698  0.30 268)
  915.         (587  0.40 268)
  916.         (rest 0.4)
  917.         (587  0.40 268)
  918.         (rest 0.4)
  919.         (523  1.60 268)).! !
  920.  
  921. !AbstractSound class methodsFor: 'examples-bach fugue' stamp: 'jm 12/17/97 16:52'!
  922. bachFugueVoice2On: aSound
  923.     "Voice two of a fugue by J. S. Bach."
  924.  
  925.     ^ self noteSequenceOn: aSound from: #(
  926.         (rest 4.8)
  927.         (1568 0.15 346)
  928.         (1480 0.15 346)
  929.         (1568 0.30 346)
  930.         (1047 0.30 346)
  931.         (1245 0.30 346)
  932.         (1568 0.15 346)
  933.         (1480 0.15 346)
  934.         (1568 0.30 346)
  935.         (1760 0.30 346)
  936.         (1175 0.30 346)
  937.         (1568 0.15 346)
  938.         (1480 0.15 346)
  939.         (1568 0.30 346)
  940.         (1760 0.30 346)
  941.         (1047 0.15 346)
  942.         (1175 0.15 346)
  943.         (1245 0.60 346)
  944.         (1175 0.15 346)
  945.         (1047 0.15 346)
  946.         (932  0.30 346)
  947.         (1245 0.15 346)
  948.         (1175 0.15 346)
  949.         (1245 0.30 346)
  950.         (784  0.30 346)
  951.         (831  0.30 346)
  952.         (1397 0.15 346)
  953.         (1245 0.15 346)
  954.         (1397 0.30 346)
  955.         (880  0.30 346)
  956.         (932  0.30 346)
  957.         (1568 0.15 346)
  958.         (1397 0.15 346)
  959.         (1568 0.30 346)
  960.         (988  0.30 346)
  961.         (1047 0.30 346)
  962.         (1175 0.15 346)
  963.         (1245 0.15 346)
  964.         (1397 0.90 346)
  965.         (1245 0.15 346)
  966.         (1175 0.15 346)
  967.         (1047 0.15 346)
  968.         (932  0.15 346)
  969.         (831  0.15 346)
  970.         (784  0.15 346)
  971.         (698  0.30 346)
  972.         (1661 0.30 346)
  973.         (1568 0.30 346)
  974.         (1397 0.30 346)
  975.         (1245 0.30 346)
  976.         (1175 0.30 346)
  977.         (1245 0.30 346)
  978.         (1397 0.30 346)
  979.         (988  0.30 346)
  980.         (1047 0.30 346)
  981.         (1175 0.30 346)
  982.         (988  0.30 346)
  983.         (1047 0.30 457)
  984.         (1568 0.15 457)
  985.         (1480 0.15 457)
  986.         (1568 0.30 457)
  987.         (1175 0.30 457)
  988.         (1245 0.60 457)
  989.         (rest 0.3)
  990.         (1319 0.30 457)
  991.         (1397 0.30 457)
  992.         (1397 0.15 457)
  993.         (1319 0.15 457)
  994.         (1397 0.30 457)
  995.         (1047 0.30 457)
  996.         (1175 0.60 457)
  997.         (rest 0.3)
  998.         (1175 0.30 457)
  999.         (1245 0.30 457)
  1000.         (1245 0.15 457)
  1001.         (1175 0.15 457)
  1002.         (1245 0.30 457)
  1003.         (932  0.30 457)
  1004.         (1047 0.30 457)
  1005.         (1245 0.15 457)
  1006.         (1175 0.15 457)
  1007.         (1245 0.30 457)
  1008.         (1397 0.30 457)
  1009.         (932  0.30 457)
  1010.         (1245 0.15 457)
  1011.         (1175 0.15 457)
  1012.         (1245 0.30 457)
  1013.         (1397 0.30 457)
  1014.         (831  0.15 457)
  1015.         (932  0.15 457)
  1016.         (1047 0.60 457)
  1017.         (932  0.15 457)
  1018.         (831  0.15 457)
  1019.         (784  0.15 457)
  1020.         (622  0.15 457)
  1021.         (698  0.15 457)
  1022.         (784  0.15 457)
  1023.         (831  0.15 457)
  1024.         (932  0.15 457)
  1025.         (1047 0.15 457)
  1026.         (1175 0.15 457)
  1027.         (1245 0.15 457)
  1028.         (1175 0.15 457)
  1029.         (1047 0.15 457)
  1030.         (1175 0.15 457)
  1031.         (1245 0.15 457)
  1032.         (1397 0.15 457)
  1033.         (1568 0.15 457)
  1034.         (1760 0.15 457)
  1035.         (1865 0.15 457)
  1036.         (698  0.15 457)
  1037.         (784  0.15 457)
  1038.         (831  0.15 457)
  1039.         (932  0.15 457)
  1040.         (1047 0.15 457)
  1041.         (1175 0.15 457)
  1042.         (1319 0.15 457)
  1043.         (1397 0.15 457)
  1044.         (1245 0.15 457)
  1045.         (1175 0.15 457)
  1046.         (1245 0.15 457)
  1047.         (1397 0.15 457)
  1048.         (1568 0.15 457)
  1049.         (1760 0.15 457)
  1050.         (1976 0.15 457)
  1051.         (2093 0.30 457)
  1052.         (1976 0.15 457)
  1053.         (1760 0.15 457)
  1054.         (1568 0.15 457)
  1055.         (1397 0.15 457)
  1056.         (1245 0.15 457)
  1057.         (1175 0.15 457)
  1058.         (1047 0.30 457)
  1059.         (1245 0.30 457)
  1060.         (1175 0.30 457)
  1061.         (1047 0.30 457)
  1062.         (932  0.30 457)
  1063.         (880  0.30 457)
  1064.         (932  0.30 457)
  1065.         (1047 0.30 457)
  1066.         (740  0.30 457)
  1067.         (784  0.30 457)
  1068.         (880  0.30 457)
  1069.         (740  0.30 457)
  1070.         (784  0.30 457)
  1071.         (1175 0.15 457)
  1072.         (1047 0.15 457)
  1073.         (1175 0.30 457)
  1074.         (rest 0.6)
  1075.         (1319 0.15 457)
  1076.         (1175 0.15 457)
  1077.         (1319 0.30 457)
  1078.         (rest 0.6)
  1079.         (1480 0.15 457)
  1080.         (1319 0.15 457)
  1081.         (1480 0.30 457)
  1082.         (rest 0.6)
  1083.         (784  0.15 457)
  1084.         (698  0.15 457)
  1085.         (784  0.30 457)
  1086.         (rest 0.6)
  1087.         (880  0.15 457)
  1088.         (784  0.15 457)
  1089.         (880  0.30 457)
  1090.         (rest 0.6)
  1091.         (988  0.15 457)
  1092.         (880  0.15 457)
  1093.         (988  0.30 457)
  1094.         (rest 0.6)
  1095.         (1047 0.15 457)
  1096.         (988  0.15 457)
  1097.         (1047 0.30 457)
  1098.         (784  0.30 457)
  1099.         (831  0.30 457)
  1100.         (1047 0.15 457)
  1101.         (988  0.15 457)
  1102.         (1047 0.30 457)
  1103.         (1175 0.30 457)
  1104.         (784  0.30 457)
  1105.         (1047 0.15 457)
  1106.         (988  0.15 457)
  1107.         (1047 0.30 457)
  1108.         (1175 0.30 457)
  1109.         (698  0.15 457)
  1110.         (784  0.15 457)
  1111.         (831  0.60 457)
  1112.         (784  0.15 457)
  1113.         (698  0.15 457)
  1114.         (622  0.30 457)
  1115.         (1047 0.15 457)
  1116.         (988  0.15 457)
  1117.         (1047 0.30 457)
  1118.         (784  0.30 457)
  1119.         (831  0.60 457)
  1120.         (rest 0.3)
  1121.         (880  0.30 457)
  1122.         (932  0.30 457)
  1123.         (932  0.15 457)
  1124.         (880  0.15 457)
  1125.         (932  0.30 457)
  1126.         (698  0.30 457)
  1127.         (784  0.60 457)
  1128.         (rest 0.3)
  1129.         (784  0.60 457)
  1130.         (831  0.15 457)
  1131.         (932  0.15 457)
  1132.         (1047 0.15 457)
  1133.         (988  0.15 457)
  1134.         (1047 0.15 457)
  1135.         (831  0.15 457)
  1136.         (698  1.20 457)
  1137.         (698  0.30 591)
  1138.         (1175 0.15 591)
  1139.         (1047 0.15 591)
  1140.         (1175 0.30 591)
  1141.         (698  0.30 591)
  1142.         (622  0.30 591)
  1143.         (1245 0.15 591)
  1144.         (1175 0.15 591)
  1145.         (1245 0.30 591)
  1146.         (784  0.30 591)
  1147.         (698  0.30 591)
  1148.         (1397 0.15 591)
  1149.         (1245 0.15 591)
  1150.         (1397 0.30 591)
  1151.         (831  0.30 591)
  1152.         (784  0.15 591)
  1153.         (1397 0.15 591)
  1154.         (1245 0.15 591)
  1155.         (1175 0.15 591)
  1156.         (1047 0.15 591)
  1157.         (988  0.15 591)
  1158.         (880  0.15 591)
  1159.         (784  0.15 591)
  1160.         (1047 0.30 591)
  1161.         (1397 0.30 591)
  1162.         (1245 0.30 591)
  1163.         (1175 0.30 591)
  1164.         (rest 0.3)
  1165.         (831  0.30 591)
  1166.         (784  0.30 591)
  1167.         (698  0.30 591)
  1168.         (784  0.30 591)
  1169.         (698  0.15 591)
  1170.         (622  0.15 591)
  1171.         (698  0.30 591)
  1172.         (587  0.30 591)
  1173.         (831  0.30 591)
  1174.         (784  0.30 591)
  1175.         (rest 0.3)
  1176.         (880  0.30 591)
  1177.         (988  0.30 591)
  1178.         (1047 0.30 591)
  1179.         (698  0.15 591)
  1180.         (622  0.15 591)
  1181.         (587  0.15 591)
  1182.         (523  0.15 591)
  1183.         (523  0.30 591)
  1184.         (1047 0.15 346)
  1185.         (988  0.15 346)
  1186.         (1047 0.30 346)
  1187.         (784  0.30 346)
  1188.         (831  0.30 346)
  1189.         (1047 0.15 346)
  1190.         (988  0.15 346)
  1191.         (1047 0.30 346)
  1192.         (1175 0.30 346)
  1193.         (784  0.30 346)
  1194.         (1047 0.15 346)
  1195.         (988  0.15 346)
  1196.         (1047 0.30 346)
  1197.         (1175 0.30 346)
  1198.         (698  0.20 346)
  1199.         (784  0.20 346)
  1200.         (831  0.80 346)
  1201.         (784  0.20 346)
  1202.         (698  0.20 346)
  1203.         (659  1.60 346)).
  1204. ! !
  1205.  
  1206. !AbstractSound class methodsFor: 'examples-bach fugue' stamp: 'jm 12/17/97 16:52'!
  1207. bachFugueVoice3On: aSound
  1208.     "Voice three of a fugue by J. S. Bach."
  1209.  
  1210.     ^ self noteSequenceOn: aSound from: #(
  1211.         (rest 14.4)
  1212.         (523  0.15 457)
  1213.         (494  0.15 457)
  1214.         (523  0.30 457)
  1215.         (392  0.30 457)
  1216.         (415  0.30 457)
  1217.         (523  0.15 457)
  1218.         (494  0.15 457)
  1219.         (523  0.30 457)
  1220.         (587  0.30 457)
  1221.         (392  0.30 457)
  1222.         (523  0.15 457)
  1223.         (494  0.15 457)
  1224.         (523  0.30 457)
  1225.         (587  0.30 457)
  1226.         (349  0.15 457)
  1227.         (392  0.15 457)
  1228.         (415  0.60 457)
  1229.         (392  0.15 457)
  1230.         (349  0.15 457)
  1231.         (311  0.15 457)
  1232.         (523  0.15 457)
  1233.         (494  0.15 457)
  1234.         (440  0.15 457)
  1235.         (392  0.15 457)
  1236.         (349  0.15 457)
  1237.         (311  0.15 457)
  1238.         (294  0.15 457)
  1239.         (262  0.15 457)
  1240.         (294  0.15 457)
  1241.         (311  0.15 457)
  1242.         (294  0.15 457)
  1243.         (262  0.15 457)
  1244.         (233  0.15 457)
  1245.         (208  0.15 457)
  1246.         (196  0.15 457)
  1247.         (175  0.15 457)
  1248.         (466  0.15 457)
  1249.         (415  0.15 457)
  1250.         (392  0.15 457)
  1251.         (349  0.15 457)
  1252.         (311  0.15 457)
  1253.         (294  0.15 457)
  1254.         (262  0.15 457)
  1255.         (233  0.15 457)
  1256.         (262  0.15 457)
  1257.         (294  0.15 457)
  1258.         (262  0.15 457)
  1259.         (233  0.15 457)
  1260.         (208  0.15 457)
  1261.         (196  0.15 457)
  1262.         (175  0.15 457)
  1263.         (156  0.15 457)
  1264.         (415  0.15 457)
  1265.         (392  0.15 457)
  1266.         (349  0.15 457)
  1267.         (311  0.15 457)
  1268.         (277  0.15 457)
  1269.         (262  0.15 457)
  1270.         (233  0.15 457)
  1271.         (208  0.30 457)
  1272.         (523  0.30 457)
  1273.         (466  0.30 457)
  1274.         (415  0.30 457)
  1275.         (392  0.30 457)
  1276.         (349  0.30 457)
  1277.         (392  0.30 457)
  1278.         (415  0.30 457)
  1279.         (294  0.30 457)
  1280.         (311  0.30 457)
  1281.         (349  0.30 457)
  1282.         (294  0.30 457)
  1283.         (311  0.30 457)
  1284.         (415  0.30 457)
  1285.         (392  0.30 457)
  1286.         (349  0.30 457)
  1287.         (392  0.30 457)
  1288.         (311  0.30 457)
  1289.         (294  0.30 457)
  1290.         (262  0.30 457)
  1291.         (294  0.30 457)
  1292.         (466  0.30 457)
  1293.         (415  0.30 457)
  1294.         (392  0.30 457)
  1295.         (415  0.30 457)
  1296.         (349  0.30 457)
  1297.         (311  0.30 457)
  1298.         (294  0.30 457)
  1299.         (311  0.30 457)
  1300.         (rest 1.2)
  1301.         (262  0.30 457)
  1302.         (233  0.30 457)
  1303.         (220  0.30 457)
  1304.         (rest 0.3)
  1305.         (311  0.30 457)
  1306.         (294  0.30 457)
  1307.         (262  0.30 457)
  1308.         (294  0.30 457)
  1309.         (262  0.15 457)
  1310.         (233  0.15 457)
  1311.         (262  0.30 457)
  1312.         (294  0.30 457)
  1313.         (196  0.30 591)
  1314.         (466  0.15 591)
  1315.         (440  0.15 591)
  1316.         (466  0.30 591)
  1317.         (294  0.30 591)
  1318.         (311  0.30 591)
  1319.         (523  0.15 591)
  1320.         (466  0.15 591)
  1321.         (523  0.30 591)
  1322.         (330  0.30 591)
  1323.         (349  0.30 591)
  1324.         (587  0.15 591)
  1325.         (523  0.15 591)
  1326.         (587  0.30 591)
  1327.         (370  0.30 591)
  1328.         (392  0.60 591)
  1329.         (rest 0.15)
  1330.         (196  0.15 591)
  1331.         (220  0.15 591)
  1332.         (247  0.15 591)
  1333.         (262  0.15 591)
  1334.         (294  0.15 591)
  1335.         (311  0.45 591)
  1336.         (220  0.15 591)
  1337.         (233  0.15 591)
  1338.         (262  0.15 591)
  1339.         (294  0.15 591)
  1340.         (311  0.15 591)
  1341.         (349  0.45 591)
  1342.         (247  0.15 591)
  1343.         (262  0.15 591)
  1344.         (294  0.15 591)
  1345.         (311  0.30 591)
  1346.         (rest 0.6)
  1347.         (330  0.30 591)
  1348.         (349  0.30 591)
  1349.         (175  0.30 591)
  1350.         (156  0.30 591)
  1351.         (147  0.30 591)
  1352.         (rest 0.3)
  1353.         (208  0.30 591)
  1354.         (196  0.30 591)
  1355.         (175  0.30 591)
  1356.         (196  0.30 591)
  1357.         (175  0.15 591)
  1358.         (156  0.15 591)
  1359.         (175  0.30 591)
  1360.         (196  0.30 591)
  1361.         (262  0.15 591)
  1362.         (294  0.15 591)
  1363.         (311  0.15 591)
  1364.         (294  0.15 591)
  1365.         (262  0.15 591)
  1366.         (233  0.15 591)
  1367.         (208  0.15 591)
  1368.         (196  0.15 591)
  1369.         (175  0.15 591)
  1370.         (466  0.15 591)
  1371.         (415  0.15 591)
  1372.         (392  0.15 591)
  1373.         (349  0.15 591)
  1374.         (311  0.15 591)
  1375.         (294  0.15 591)
  1376.         (262  0.15 591)
  1377.         (233  0.15 591)
  1378.         (262  0.15 591)
  1379.         (294  0.15 591)
  1380.         (262  0.15 591)
  1381.         (233  0.15 591)
  1382.         (208  0.15 591)
  1383.         (196  0.15 591)
  1384.         (175  0.15 591)
  1385.         (156  0.15 591)
  1386.         (415  0.15 591)
  1387.         (392  0.15 591)
  1388.         (349  0.15 591)
  1389.         (311  0.15 591)
  1390.         (294  0.15 591)
  1391.         (262  0.15 591)
  1392.         (233  0.15 591)
  1393.         (208  0.15 591)
  1394.         (233  0.15 591)
  1395.         (262  0.15 591)
  1396.         (233  0.15 591)
  1397.         (208  0.15 591)
  1398.         (196  0.15 591)
  1399.         (175  0.15 591)
  1400.         (156  0.15 591)
  1401.         (147  0.15 591)
  1402.         (392  0.15 591)
  1403.         (349  0.15 591)
  1404.         (311  0.15 591)
  1405.         (294  0.15 591)
  1406.         (262  0.15 591)
  1407.         (247  0.15 591)
  1408.         (220  0.15 591)
  1409.         (196  0.60 772)
  1410.         (196  0.60 772)
  1411.         (rest 0.15)
  1412.         (196  0.15 772)
  1413.         (220  0.15 772)
  1414.         (247  0.15 772)
  1415.         (262  0.15 772)
  1416.         (294  0.15 772)
  1417.         (311  0.15 772)
  1418.         (349  0.15 772)
  1419.         (392  0.15 772)
  1420.         (349  0.15 772)
  1421.         (415  0.15 772)
  1422.         (392  0.15 772)
  1423.         (349  0.15 772)
  1424.         (311  0.15 772)
  1425.         (294  0.15 772)
  1426.         (262  0.15 772)
  1427.         (247  0.30 772)
  1428.         (262  0.15 772)
  1429.         (494  0.15 772)
  1430.         (262  0.30 772)
  1431.         (196  0.30 772)
  1432.         (208  0.30 772)
  1433.         (262  0.15 772)
  1434.         (247  0.15 772)
  1435.         (262  0.30 772)
  1436.         (294  0.30 772)
  1437.         (196  0.30 772)
  1438.         (262  0.15 772)
  1439.         (247  0.15 772)
  1440.         (262  0.30 772)
  1441.         (294  0.30 772)
  1442.         (175  0.15 772)
  1443.         (196  0.15 772)
  1444.         (208  0.60 772)
  1445.         (196  0.15 772)
  1446.         (175  0.15 772)
  1447.         (156  0.60 772)
  1448.         (rest 0.3)
  1449.         (311  0.30 772)
  1450.         (294  0.30 772)
  1451.         (262  0.30 772)
  1452.         (392  0.30 772)
  1453.         (196  0.30 772)
  1454.         (262  3.60 268)
  1455.         (494  0.40 268)
  1456.         (rest 0.4)
  1457.         (494  0.40 268)
  1458.         (rest 0.4)
  1459.         (392  1.60 268)).
  1460. ! !
  1461.  
  1462. !AbstractSound class methodsFor: 'examples-bach fugue' stamp: 'jm 12/17/97 16:52'!
  1463. bachFugueVoice4On: aSound
  1464.     "Voice four of a fugue by J. S. Bach."
  1465.  
  1466.     ^ self noteSequenceOn: aSound from: #(
  1467.         (rest 61.2)
  1468.         (131  0.15 500)
  1469.         (123  0.15 500)
  1470.         (131  0.30 500)
  1471.         (98   0.30 500)
  1472.         (104  0.30 500)
  1473.         (131  0.15 500)
  1474.         (123  0.15 500)
  1475.         (131  0.30 500)
  1476.         (147  0.30 500)
  1477.         (98   0.30 500)
  1478.         (131  0.15 500)
  1479.         (123  0.15 500)
  1480.         (131  0.30 500)
  1481.         (147  0.30 500)
  1482.         (87   0.15 500)
  1483.         (98   0.15 500)
  1484.         (104  0.60 500)
  1485.         (98   0.15 500)
  1486.         (87   0.15 500)
  1487.         (78   0.60 500)
  1488.         (rest 0.3)
  1489.         (156  0.30 500)
  1490.         (147  0.30 500)
  1491.         (131  0.30 500)
  1492.         (196  0.30 500)
  1493.         (98   0.30 500)
  1494.         (131  3.60 268)
  1495.         (131  3.20 205)).
  1496. ! !
  1497.  
  1498. !AbstractSound class methodsFor: 'examples-bach fugue' stamp: 'jm 1/5/98 17:45'!
  1499. stereoBachFugue
  1500.     "Play fugue by J. S. Bach in stereo using different timbres."
  1501.     "AbstractSound stereoBachFugue play"
  1502.  
  1503.     "(AbstractSound bachFugueVoice1On: FMSound flute1) play"
  1504.     "(AbstractSound bachFugueVoice1On: PluckedSound default) play"
  1505.  
  1506.     ^ MixedSound new
  1507.         add: (self bachFugueVoice1On: FMSound oboe1) pan: 0.2;
  1508.         add: (self bachFugueVoice2On: FMSound organ1) pan: 0.8;
  1509.         add: (self bachFugueVoice3On: PluckedSound default) pan: 0.4;
  1510.         add: (self bachFugueVoice4On: FMSound brass1) pan: 0.6.
  1511. ! !
  1512.  
  1513.  
  1514. !AbstractSound class methodsFor: 'primitive generation' stamp: 'jm 1/21/98 17:08'!
  1515. cCodeForSoundPrimitives
  1516.     "Return a string containing the C code for the sound primitives. This string is pasted into a file, compiled, and linked into the virtual machine. Note that the virtual machine's primitive table must also be edited to make new primitives available."
  1517.     "AbstractSound cCodeForSoundPrimitives"
  1518.  
  1519.     ^ CCodeGenerator new codeStringForPrimitives: #(
  1520.         (FMSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  1521.         (PluckedSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  1522.         (SampledSound mixSampleCount:into:startingAt:leftVol:rightVol:)
  1523.         (ReverbSound applyReverbTo:startingAt:count:)
  1524.     ).
  1525. ! !
  1526.  
  1527.  
  1528. !AbstractSound class methodsFor: 'sounds' stamp: 'di 1/27/98 15:12'!
  1529. initSounds  "AbstractSound initSounds"
  1530.     Sounds _ Dictionary new.
  1531.     (FMSound class organization listAtCategoryNamed: #instruments)
  1532.         do: [:soundName | Sounds at: soundName asString
  1533.                         put: (FMSound perform: soundName)]! !
  1534.  
  1535. !AbstractSound class methodsFor: 'sounds' stamp: 'di 1/27/98 15:13'!
  1536. soundNamed: soundName
  1537.     ^ Sounds at: soundName! !
  1538.  
  1539. !AbstractSound class methodsFor: 'sounds' stamp: 'jm 3/4/98 10:29'!
  1540. soundNamed: soundName ifAbsent: aBlock
  1541.  
  1542.     ^ Sounds at: soundName ifAbsent: aBlock
  1543. ! !
  1544.  
  1545. !AbstractSound class methodsFor: 'sounds' stamp: 'jm 5/16/1998 09:54'!
  1546. soundNamed: soundName put: aSound
  1547.  
  1548.     Sounds at: soundName put: aSound.
  1549.     Smalltalk at: #ScorePlayerMorph ifPresent: [:playerClass |
  1550.         playerClass allInstancesDo:
  1551.             [:player | player updateInstrumentsFromLibrary]].
  1552. ! !
  1553.  
  1554. !AbstractSound class methodsFor: 'sounds' stamp: 'di 1/27/98 15:13'!
  1555. soundNames
  1556.     ^ Sounds keys! !
  1557. FileDirectory subclass: #AcornFileDirectory
  1558.     instanceVariableNames: ''
  1559.     classVariableNames: 'FormsAreLittleEndian '
  1560.     poolDictionaries: ''
  1561.     category: 'System-Files'!
  1562.  
  1563. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  1564.  
  1565. AcornFileDirectory class
  1566.     instanceVariableNames: ''!
  1567.  
  1568. !AcornFileDirectory class methodsFor: 'platform specific' stamp: 'jm 3/27/98 09:24'!
  1569. byteReverseForm: aForm
  1570.     "Byte-reverse the words of the given Form's bitmap. Supports porting a Squeak image to the Acorn."
  1571.  
  1572.     | bits w reversedW |
  1573.     bits _ aForm bits.
  1574.     1 to: bits size do: [:i |
  1575.         w _ bits at: i.
  1576.         reversedW _ Integer
  1577.             byte1: (w digitAt: 4)
  1578.             byte2: (w digitAt: 3)
  1579.             byte3: (w digitAt: 2)
  1580.             byte4: (w digitAt: 1).
  1581.         bits at: i put: reversedW].
  1582. ! !
  1583.  
  1584. !AcornFileDirectory class methodsFor: 'platform specific' stamp: 'jm 3/27/98 06:44'!
  1585. extensionDelimiter
  1586.     "Return the character used to delimit filename extensions. For the Acorn, use a slash, since that is what a dot gets converted to when loading files from foreign file systems."
  1587.  
  1588.     ^ $/
  1589. ! !
  1590.  
  1591. !AcornFileDirectory class methodsFor: 'platform specific' stamp: 'jm 3/27/98 06:41'!
  1592. pathNameDelimiter
  1593.  
  1594.     ^ $.
  1595. ! !
  1596.  
  1597. !AcornFileDirectory class methodsFor: 'platform specific' stamp: 'jm 3/27/98 09:25'!
  1598. platformSpecificStartup
  1599.     "Do platform-specific startup. This is a hook for starting up a default Squeak image on an Acorn, whose BitBlt expects Forms to have little-endian byte ordering."
  1600.  
  1601.     FormsAreLittleEndian ifNil: [FormsAreLittleEndian _ false].
  1602.     FormsAreLittleEndian ifTrue: [^ self].  "already converted"
  1603.  
  1604.     Form withAllSubclasses do: [:c |
  1605.         c allInstancesDo: [:f |
  1606.             "skip the Display, since it will be redrawn anyway"
  1607.             f == Display ifFalse: [self byteReverseForm: f]]].
  1608.  
  1609.     FormsAreLittleEndian _ true.
  1610. ! !
  1611. SwikiAction subclass: #ActiveSwikiAction
  1612.     instanceVariableNames: ''
  1613.     classVariableNames: ''
  1614.     poolDictionaries: ''
  1615.     category: 'PluggableWebServer'!
  1616.  
  1617. !ActiveSwikiAction methodsFor: 'as yet unclassified' stamp: 'ls 5/1/98 11:29'!
  1618. browse: pageRef from: request
  1619.     "Just reply with a page in HTML format"
  1620.  
  1621.     | formattedPage liveText|
  1622.     liveText _ HTMLformatter evalEmbedded: (pageRef text)
  1623.         with: request unlessContains: (self dangerSet).
  1624.     formattedPage _ pageRef copy.
  1625.     "Make a copy, then format the text."
  1626.     formattedPage formatted: (HTMLformatter swikify: liveText
  1627.             linkhandler: [:link | urlmap
  1628.                     linkFor: link
  1629.                     from: request peerName
  1630.                     storingTo: OrderedCollection new]).
  1631.     request reply: ((self formatterFor: 'page') format: formattedPage).
  1632. ! !
  1633.  
  1634. !ActiveSwikiAction methodsFor: 'as yet unclassified' stamp: 'tk 2/4/98 12:52'!
  1635. dangerSet
  1636.     ^#('Smalltalk' 'view' 'open' 'perform:' 'FileStream' 'FileDirectory' 'fileIn' 'Compiler' 'halt'
  1637.     'PWS' 'Swiki')
  1638. ! !
  1639.  
  1640. !ActiveSwikiAction methodsFor: 'as yet unclassified' stamp: 'tk 1/31/98 16:44'!
  1641. inputFrom: request
  1642.     "Take user's input and respond with a searchresult or store the edit"
  1643.  
  1644.     | coreRef page |
  1645.     coreRef _ request message size < 2
  1646.         ifTrue: ['1']
  1647.         ifFalse: [request message at: 2].
  1648.     coreRef = 'searchresult' ifTrue: [
  1649.         "If contains search string, do search"
  1650.         request reply: PWS crlf, 
  1651.             (HTMLformatter evalEmbedded: (self fileContents: source, 'results.html')
  1652.                 with: (urlmap searchFor: (request fields at: 'searchFor' ifAbsent: ['nothing']))).
  1653.         ^ #return].
  1654.     (request fields includesKey: 'text') ifTrue: ["It's a response from an edit, so store the page"
  1655.         page _ urlmap
  1656.             storeID: coreRef
  1657.             text: (request fields at: 'text' ifAbsent: ['blank text'])
  1658.             from: request peerName.
  1659.         page user: request userID.
  1660.         ^ self].    "return self means do serve the edited page afterwards"
  1661.     "oops, a new kind!! -- but don't complain!! Could be for ActivePage!!"
  1662. "    Transcript show: 'Unknown data from client. '; show: request fields
  1663. printString; cr."! !
  1664. SketchMorph subclass: #ActorDroneMorph
  1665.     instanceVariableNames: 'running clan '
  1666.     classVariableNames: 'ClanCache OnTicksSelectorCache '
  1667.     poolDictionaries: ''
  1668.     category: 'Experimental-Miscellaneous'!
  1669. !ActorDroneMorph commentStamp: 'di 5/22/1998 16:32' prior: 0!
  1670. ActorDroneMorph comment:
  1671. 'I am a class of ActorMorphs that all share the same behavior methods.  OnTicks defined for one of me is used for all of me as long as we are of the same clan.  Clan is a symbol that is our name.'!
  1672.  
  1673.  
  1674. !ActorDroneMorph methodsFor: 'all' stamp: 'tk 8/20/97 09:07'!
  1675. clan
  1676.     ^ clan! !
  1677.  
  1678. !ActorDroneMorph methodsFor: 'all' stamp: 'sw 8/17/97 23:00'!
  1679. clan: aSymbol
  1680.     clan _ aSymbol! !
  1681.  
  1682. !ActorDroneMorph methodsFor: 'all' stamp: 'sw 8/17/97 22:59'!
  1683. nameInModel
  1684.     ^ clan! !
  1685.  
  1686. !ActorDroneMorph methodsFor: 'all' stamp: 'tk 8/21/97 13:22'!
  1687. onTicksSelector
  1688.     "Cache the interned symbol.  Should intern: do this?"
  1689.  
  1690.     clan = ClanCache ifTrue: [^ OnTicksSelectorCache].
  1691.     ClanCache _ clan.
  1692.     ^ OnTicksSelectorCache _ (self nameInModel, 'OnTicks:') asSymbol
  1693. ! !
  1694.  
  1695. !ActorDroneMorph methodsFor: 'all' stamp: 'sw 8/18/97 13:41'!
  1696. step
  1697.  
  1698.     running ifTrue: [
  1699.         self world model perform: self onTicksSelector with: self].
  1700. ! !
  1701.  
  1702. !ActorDroneMorph methodsFor: 'all' stamp: 'tk 8/27/97 23:46'!
  1703. stepTime
  1704.  
  1705.     ^ 0! !
  1706. Object subclass: #ActorState
  1707.     instanceVariableNames: 'owningPlayer penDown penSize penColor fractionalPosition instantiatedUserScriptsDictionary '
  1708.     classVariableNames: ''
  1709.     poolDictionaries: ''
  1710.     category: 'Morphic-Scripting-Support'!
  1711. !ActorState commentStamp: 'di 5/22/1998 16:32' prior: 0!
  1712. Holds a record of data representing actor-like slots in the Morph, on behalf of an associated Player.  Presently also holds onto the scriptInstantion objects that represent active scripts in an instance, but this will probably change soon.!
  1713.  
  1714.  
  1715. !ActorState methodsFor: 'initialization' stamp: 'sw 4/30/1998 22:32'!
  1716. copyWithPlayerReferenceNilled
  1717.     "Answer a copy of the receiver in which all the items referring to the corresponding Player object are nilled out, for the purpose of being set up with fresh values, after the copy, by the caller"
  1718.  
  1719.     | holdPlayer holdScriptDict copy copyScriptDict |
  1720.     holdPlayer _ owningPlayer.
  1721.     owningPlayer _ nil.
  1722.     holdScriptDict _ self instantiatedUserScriptsDictionary.
  1723.     instantiatedUserScriptsDictionary _ nil.
  1724.     copy _ self deepCopy.
  1725.     owningPlayer _ holdPlayer.
  1726.     instantiatedUserScriptsDictionary _ holdScriptDict.
  1727.     holdScriptDict ifNotNil:
  1728.         [copyScriptDict _ IdentityDictionary new.
  1729.         holdScriptDict associationsDo:
  1730.             [:assoc |
  1731.                 copyScriptDict add: (assoc key -> (assoc value copyWithPlayerObliterated))].
  1732.         copy instantiatedUserScriptsDictionary: copyScriptDict].
  1733.     ^ copy
  1734. ! !
  1735.  
  1736. !ActorState methodsFor: 'initialization' stamp: 'sw 5/13/1998 16:37'!
  1737. initializeFor: aPlayer
  1738.     | aNewDictionary |
  1739.     owningPlayer _ aPlayer.
  1740.     instantiatedUserScriptsDictionary ifNil: [^ self].
  1741.     aNewDictionary _ IdentityDictionary new.
  1742.     instantiatedUserScriptsDictionary associationsDo: 
  1743.         [:assoc |
  1744.             aNewDictionary at: assoc key put: (assoc value shallowCopy player: aPlayer)].
  1745.     instantiatedUserScriptsDictionary _ aNewDictionary.! !
  1746.  
  1747.  
  1748. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:51'!
  1749. choosePenColor: evt
  1750.     evt hand changeColorTarget: owningPlayer costume selector: #penColor:.
  1751. ! !
  1752.  
  1753. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:44'!
  1754. choosePenSize
  1755.     | menu sz |
  1756.     menu _ CustomMenu new.
  1757.     1 to: 10 do: [:w | menu add: w printString action: w].
  1758.     sz _ menu startUp.
  1759.     sz ifNotNil: [penSize _ sz]! !
  1760.  
  1761. !ActorState methodsFor: 'pen' stamp: 'sw 2/4/98 15:16'!
  1762. defaultPenColor
  1763.     ^ Color blue! !
  1764.  
  1765. !ActorState methodsFor: 'pen' stamp: 'sw 2/4/98 15:03'!
  1766. defaultPenSize
  1767.     ^ 1! !
  1768.  
  1769. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:35'!
  1770. getPenColor
  1771.     penColor ifNil: [penColor _ self defaultPenColor].
  1772.     ^ penColor! !
  1773.  
  1774. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:40'!
  1775. getPenDown
  1776.     ^ penDown == true! !
  1777.  
  1778. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:43'!
  1779. getPenSize
  1780.     penSize ifNil: [penSize _ self defaultPenSize].
  1781.     ^ penSize! !
  1782.  
  1783. !ActorState methodsFor: 'pen' stamp: 'sw 2/4/98 18:07'!
  1784. liftPen
  1785.     penDown _ false! !
  1786.  
  1787. !ActorState methodsFor: 'pen' stamp: 'sw 2/4/98 14:58'!
  1788. lowerPen
  1789.     penDown _ true! !
  1790.  
  1791. !ActorState methodsFor: 'pen' stamp: 'sw 2/4/98 18:03'!
  1792. penColor: aColor
  1793.     penColor _ aColor! !
  1794.  
  1795. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:51'!
  1796. setPenColor: aColor
  1797.     penColor _ aColor
  1798. ! !
  1799.  
  1800. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:47'!
  1801. setPenDown: aBoolean
  1802.     penDown _ aBoolean! !
  1803.  
  1804. !ActorState methodsFor: 'pen' stamp: 'sw 4/22/1998 13:45'!
  1805. setPenSize: aNumber
  1806.     penSize _ aNumber! !
  1807.  
  1808.  
  1809. !ActorState methodsFor: 'position' stamp: 'jm 4/24/1998 21:34'!
  1810. fractionalPosition
  1811.     "Return my player's costume's position including the fractional part. This allows the precise position to be retained to avoid cummulative rounding errors, while letting Morphic do all its calculations with integer pixel coordinates. See the implementation of forward:."
  1812.  
  1813.     ^ fractionalPosition
  1814. ! !
  1815.  
  1816. !ActorState methodsFor: 'position' stamp: 'jm 4/24/1998 21:31'!
  1817. fractionalPosition: aPoint
  1818.  
  1819.     fractionalPosition _ aPoint asFloatPoint.
  1820. ! !
  1821.  
  1822.  
  1823. !ActorState methodsFor: 'script instantiations' stamp: 'sw 4/9/98 22:35'!
  1824. instantiatedUserScriptsDictionary
  1825.     instantiatedUserScriptsDictionary ifNil: [instantiatedUserScriptsDictionary _ IdentityDictionary new].
  1826.     ^ instantiatedUserScriptsDictionary! !
  1827.  
  1828. !ActorState methodsFor: 'script instantiations' stamp: 'sw 4/30/1998 21:51'!
  1829. instantiatedUserScriptsDictionary: aDict
  1830.     "Used for copying code only"
  1831.     instantiatedUserScriptsDictionary _ aDict! !
  1832.  
  1833.  
  1834. !ActorState methodsFor: 'other' stamp: 'sw 4/22/1998 17:02'!
  1835. addPlayerMenuItemsTo: aMenu hand: aHandMorph
  1836.     self getPenDown
  1837.         ifTrue: [aMenu add: 'pen up' action: #liftPen]
  1838.         ifFalse: [aMenu add: 'pen down' action: #lowerPen].
  1839.     aMenu add: 'pen size' action: #choosePenSize.
  1840.     aMenu add: 'pen color' action: #choosePenColor:.! !
  1841.  
  1842. !ActorState methodsFor: 'other' stamp: 'sw 4/13/1998 19:36'!
  1843. costume
  1844.     ^ owningPlayer costume! !
  1845.  
  1846. !ActorState methodsFor: 'other' stamp: 'sw 5/12/1998 23:35'!
  1847. printOn: aStream
  1848.     aStream nextPutAll: 'ActorState for ', owningPlayer externalName, ' '.
  1849.     penDown ifNotNil: [aStream cr; nextPutAll: 'penDown ', penDown printString].
  1850.     penColor ifNotNil: [aStream cr; nextPutAll: 'penColor ', penColor printString].
  1851.     penSize ifNotNil: [aStream cr; nextPutAll: 'penSize ', penSize printString].
  1852.     instantiatedUserScriptsDictionary ifNotNil:
  1853.         [aStream cr; nextPutAll:
  1854.             '+ ', instantiatedUserScriptsDictionary size printString, ' user scripts'].
  1855. ! !
  1856. RectangleMorph subclass: #AlignmentMorph
  1857.     instanceVariableNames: 'orientation centering hResizing vResizing inset minCellSize openToDragNDrop layoutNeeded '
  1858.     classVariableNames: ''
  1859.     poolDictionaries: ''
  1860.     category: 'Morphic-Basic'!
  1861.  
  1862. !AlignmentMorph methodsFor: 'initialization' stamp: 'sw 9/10/97 14:47'!
  1863. initialize
  1864.  
  1865.     super initialize.
  1866.     borderWidth _ 0.
  1867.     orientation _ #horizontal.    "#horizontal or #vertical  or #free"
  1868.     centering _ #topLeft.        "#topLeft, #center, or #bottomRight"
  1869.     hResizing _ #spaceFill.        "#spaceFill, #shrinkWrap, or #rigid"
  1870.     vResizing _ #spaceFill.        "#spaceFill, #shrinkWrap, or #rigid"
  1871.     inset _ 2.                    "pixels inset within owner's bounds"
  1872.     minCellSize _ 0.                "minimum space between morphs; useful for tables"
  1873.     openToDragNDrop _ false.    "objects can be dropped in or dragged out"
  1874.     layoutNeeded _ true.
  1875.     color _ Color r: 0.8 g: 1.0 b: 0.8.
  1876. ! !
  1877.  
  1878.  
  1879. !AlignmentMorph methodsFor: 'classification' stamp: 'sw 5/13/1998 14:50'!
  1880. demandsBoolean
  1881.     "unique to the TEST frame inside a CompoundTileMorph"
  1882.  
  1883.     ^ self hasProperty: #demandsBoolean! !
  1884.  
  1885. !AlignmentMorph methodsFor: 'classification' stamp: 'di 5/7/1998 01:20'!
  1886. isAlignmentMorph
  1887.  
  1888.     ^ true
  1889. ! !
  1890.  
  1891.  
  1892. !AlignmentMorph methodsFor: 'accessing'!
  1893. centering
  1894.  
  1895.     ^ centering
  1896. ! !
  1897.  
  1898. !AlignmentMorph methodsFor: 'accessing'!
  1899. centering: aSymbol
  1900.     "Set the minor dimension alignment to #topLeft, #center, or #bottomRight."
  1901.  
  1902.     centering _ aSymbol.
  1903. ! !
  1904.  
  1905. !AlignmentMorph methodsFor: 'accessing' stamp: 'sw 2/13/98 16:15'!
  1906. chooseOrientation
  1907.     | aMenu emphases reply |
  1908.     emphases _ #(vertical horizontal).
  1909.     aMenu _ EmphasizedMenu selections: emphases.
  1910.     aMenu onlyBoldItem: (emphases indexOf: orientation).
  1911.     reply _ aMenu startUpWithCaption: 'Choose orientation'.
  1912.     (reply == nil or: [reply == orientation]) ifTrue: [^ self].
  1913.     self orientation: reply.
  1914.     self layoutChanged! !
  1915.  
  1916. !AlignmentMorph methodsFor: 'accessing' stamp: 'sw 10/19/97 23:39'!
  1917. configureForKids
  1918.     self openToDragNDrop: false.
  1919.     super configureForKids
  1920. ! !
  1921.  
  1922. !AlignmentMorph methodsFor: 'accessing'!
  1923. hResizing
  1924.  
  1925.     ^ hResizing
  1926. ! !
  1927.  
  1928. !AlignmentMorph methodsFor: 'accessing'!
  1929. hResizing: aSymbol
  1930.     "Set the horizontal resizing style to #spaceFill, #shrinkWrap, or #rigid."
  1931.  
  1932.     hResizing _ aSymbol.
  1933. ! !
  1934.  
  1935. !AlignmentMorph methodsFor: 'accessing'!
  1936. inset
  1937.  
  1938.     ^ inset
  1939. ! !
  1940.  
  1941. !AlignmentMorph methodsFor: 'accessing'!
  1942. inset: anInteger
  1943.     "Set the amount of padding within my bounds to the given amount."
  1944.  
  1945.     inset _ anInteger.
  1946. ! !
  1947.  
  1948. !AlignmentMorph methodsFor: 'accessing'!
  1949. minCellSize
  1950.  
  1951.     ^ minCellSize
  1952. ! !
  1953.  
  1954. !AlignmentMorph methodsFor: 'accessing'!
  1955. minCellSize: anInteger
  1956.     "Set the minium space per submorph to the given size. Useful for making tables."
  1957.  
  1958.     minCellSize _ anInteger.
  1959. ! !
  1960.  
  1961. !AlignmentMorph methodsFor: 'accessing'!
  1962. openCloseDragNDrop
  1963.     "Toggle this morph's ability to add and remove morphs via drag-n-drop."
  1964.  
  1965.     openToDragNDrop _ openToDragNDrop not.
  1966. ! !
  1967.  
  1968. !AlignmentMorph methodsFor: 'accessing'!
  1969. openToDragNDrop
  1970.  
  1971.     ^ openToDragNDrop
  1972. ! !
  1973.  
  1974. !AlignmentMorph methodsFor: 'accessing'!
  1975. openToDragNDrop: aBoolean
  1976.     "Set this morph's ability to add and remove morphs via drag-n-drop."
  1977.  
  1978.     openToDragNDrop _ aBoolean.
  1979. ! !
  1980.  
  1981. !AlignmentMorph methodsFor: 'accessing'!
  1982. orientation
  1983.  
  1984.     ^ orientation
  1985. ! !
  1986.  
  1987. !AlignmentMorph methodsFor: 'accessing' stamp: 'sw 9/10/97 14:55'!
  1988. orientation: aSymbol
  1989.     "Set the major layout dimension to #horizontal or #vertical or #free"
  1990.  
  1991.     orientation _ aSymbol.
  1992. ! !
  1993.  
  1994. !AlignmentMorph methodsFor: 'accessing'!
  1995. vResizing
  1996.  
  1997.     ^ vResizing
  1998. ! !
  1999.  
  2000. !AlignmentMorph methodsFor: 'accessing'!
  2001. vResizing: aSymbol
  2002.     "Set the vertical resizing style to #spaceFill, #shrinkWrap, or #rigid."
  2003.  
  2004.     vResizing _ aSymbol.
  2005. ! !
  2006.  
  2007.  
  2008. !AlignmentMorph methodsFor: 'geometry' stamp: 'jm 7/8/97 08:26'!
  2009. layoutChanged
  2010.  
  2011.     "invalidate old fullBounds in case we shrink"
  2012.     fullBounds ifNotNil: [self invalidRect: fullBounds].
  2013.  
  2014.     super layoutChanged.
  2015.     layoutNeeded _ true.
  2016. ! !
  2017.  
  2018.  
  2019. !AlignmentMorph methodsFor: 'dropping/grabbing' stamp: 'sw 10/18/97 18:03'!
  2020. acceptDroppingMorph: aMorph event: evt
  2021.     "Allow the user to add submorphs just by dropping them on this morph."
  2022.     self privateAddMorph: aMorph atIndex: (self insertionIndexFor: aMorph).
  2023.     self changed.
  2024.     self layoutChanged.
  2025. ! !
  2026.  
  2027. !AlignmentMorph methodsFor: 'dropping/grabbing'!
  2028. allowSubmorphExtraction
  2029.  
  2030.     ^ openToDragNDrop
  2031. ! !
  2032.  
  2033. !AlignmentMorph methodsFor: 'dropping/grabbing' stamp: 'sw 10/18/97 18:19'!
  2034. rootForGrabOf: aMorph
  2035.  
  2036.     | root |
  2037.     openToDragNDrop ifFalse: [^ super rootForGrabOf: aMorph].
  2038.     root _ aMorph.
  2039.     [root == self] whileFalse:
  2040.         [root owner = self ifTrue: [^ root].
  2041.         root _ root owner].
  2042.     ^ super rootForGrabOf: aMorph
  2043. ! !
  2044.  
  2045. !AlignmentMorph methodsFor: 'dropping/grabbing'!
  2046. wantsDroppedMorph: aMorph event: evt
  2047.     "Supports adding morphs by dropping."
  2048.  
  2049.     ^ openToDragNDrop! !
  2050.  
  2051.  
  2052. !AlignmentMorph methodsFor: 'layout'!
  2053. fullBounds
  2054.     "This is the hook that triggers lazy re-layout of layout morphs. It works because layoutChanged clears the fullBounds cache. Once per cycle, the fullBounds is requested from every morph in the world, and that request gets propagated through the entire submorph hierarchy, causing re-layout where needed. Note that multiple layoutChanges to the same morph can be done with little cost, since the layout is only done when the morph needs to be displayed."
  2055.  
  2056.     fullBounds ifNil: [
  2057.         layoutNeeded ifTrue: [
  2058.             self resizeIfNeeded.
  2059.             self fixLayout.
  2060.             "compute fullBounds before calling changed to avoid infinite recursion"
  2061.             super fullBounds.  "updates cache"
  2062.             self changed.  "report change due to layout"
  2063.             layoutNeeded _ false]].
  2064.     ^ super fullBounds
  2065. ! !
  2066.  
  2067. !AlignmentMorph methodsFor: 'layout' stamp: 'sw 2/13/98 16:15'!
  2068. maxWidth
  2069.     "Return the minimum width for this morph."
  2070.  
  2071.     | spaceNeeded minW |
  2072.     hResizing = #rigid ifTrue: [^ self fullBounds width].
  2073.     submorphs isEmpty ifTrue: [^ self minWidthWhenEmpty].
  2074.     orientation == #horizontal ifTrue:
  2075.         [spaceNeeded _ 2 * (inset + borderWidth).
  2076.         submorphs do: [:m | spaceNeeded _ spaceNeeded + (m minWidth max: minCellSize)]].
  2077.     orientation == #vertical ifTrue:
  2078.         [minW _ 0.
  2079.         submorphs do: [:m | minW _ minW max: m minWidth].
  2080.         spaceNeeded _ minW + (2 * (inset + borderWidth))].
  2081.     ^ spaceNeeded! !
  2082.  
  2083. !AlignmentMorph methodsFor: 'layout' stamp: 'sw 2/13/98 16:15'!
  2084. minHeight
  2085.     "Return the minimum height for this morph."
  2086.  
  2087.     | minH spaceNeeded |
  2088.     vResizing = #rigid ifTrue: [^ self fullBounds height].
  2089.     submorphs isEmpty ifTrue: [^ self minHeightWhenEmpty].
  2090.     orientation == #horizontal ifTrue:
  2091.         [minH _ 0.
  2092.         submorphs do: [:m | minH _ minH max: m minHeight].
  2093.         spaceNeeded _ minH + (2 * (inset + borderWidth))].
  2094.     orientation == #vertical ifTrue:
  2095.         [spaceNeeded _ 2 * (inset + borderWidth).
  2096.         submorphs do: [:m | spaceNeeded _ spaceNeeded + (m minHeight max: minCellSize)]].
  2097.  
  2098.     ^ spaceNeeded
  2099. ! !
  2100.  
  2101. !AlignmentMorph methodsFor: 'layout' stamp: 'jm 1/29/98 19:43'!
  2102. minHeightWhenEmpty
  2103.  
  2104.     ^ 2
  2105. ! !
  2106.  
  2107. !AlignmentMorph methodsFor: 'layout' stamp: 'sw 2/13/98 16:15'!
  2108. minWidth
  2109.     "Return the minimum width for this morph."
  2110.  
  2111.     | spaceNeeded minW |
  2112.     hResizing = #rigid ifTrue: [^ self fullBounds width].
  2113.     submorphs isEmpty ifTrue: [^ self minWidthWhenEmpty].
  2114.     orientation == #horizontal ifTrue:
  2115.         [spaceNeeded _ 2 * (inset + borderWidth).
  2116.         submorphs do: [:m | spaceNeeded _ spaceNeeded + (m minWidth max: minCellSize)]].
  2117.     orientation == #vertical ifTrue:
  2118.         [minW _ 0.
  2119.         submorphs do: [:m | minW _ minW max: m minWidth].
  2120.         spaceNeeded _ minW + (2 * (inset + borderWidth))].
  2121.     ^ spaceNeeded! !
  2122.  
  2123. !AlignmentMorph methodsFor: 'layout' stamp: 'jm 1/29/98 19:43'!
  2124. minWidthWhenEmpty
  2125.  
  2126.     ^ 2
  2127. ! !
  2128.  
  2129.  
  2130. !AlignmentMorph methodsFor: 'menu' stamp: 'sw 9/11/97 16:07'!
  2131. addCustomMenuItems: aCustomMenu hand: aHandMorph
  2132.  
  2133.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  2134.     aCustomMenu add: 'orientation...' action: #chooseOrientation.
  2135.     aCustomMenu add: (openToDragNDrop ifTrue: ['close'] ifFalse: ['open']) , ' dragNdrop'
  2136.             action: #openCloseDragNDrop.
  2137. ! !
  2138.  
  2139.  
  2140. !AlignmentMorph methodsFor: 'private' stamp: 'di 5/7/1998 01:21'!
  2141. extraSpacePerMorph
  2142.  
  2143.     | spaceFillingMorphs spaceNeeded extra |
  2144.     spaceFillingMorphs _ 0.
  2145.     spaceNeeded _ 2 * (inset + borderWidth).
  2146.     orientation = #horizontal ifTrue: [
  2147.         submorphs do: [:m |
  2148.             spaceNeeded _ spaceNeeded + (m minWidth max: minCellSize).
  2149.             (m isAlignmentMorph and: [m hResizing = #spaceFill])
  2150.                 ifTrue: [spaceFillingMorphs _ spaceFillingMorphs + 1]].
  2151.         extra _ (bounds width - spaceNeeded) max: 0.
  2152.     ] ifFalse: [
  2153.         submorphs do: [:m |
  2154.             spaceNeeded _ spaceNeeded + (m minHeight max: minCellSize).
  2155.             (m isAlignmentMorph and: [m vResizing = #spaceFill])
  2156.                 ifTrue: [spaceFillingMorphs _ spaceFillingMorphs + 1]].
  2157.         extra _ (bounds height - spaceNeeded) max: 0].
  2158.  
  2159.     (submorphs size <= 1 or: [spaceFillingMorphs <= 1]) ifTrue: [^ extra].
  2160.     ^ extra // spaceFillingMorphs
  2161. ! !
  2162.  
  2163. !AlignmentMorph methodsFor: 'private' stamp: 'sw 2/13/98 16:15'!
  2164. fixLayout
  2165.  
  2166.     | extraPerMorph nextPlace space |
  2167.     extraPerMorph _ self extraSpacePerMorph.
  2168.     orientation = #horizontal
  2169.         ifTrue: [nextPlace _ bounds left + inset + borderWidth]
  2170.         ifFalse: [nextPlace _ bounds top + inset + borderWidth].
  2171.     submorphs do: [:m |
  2172.         space _ self placeAndSize: m at: nextPlace padding: extraPerMorph.
  2173.         nextPlace _ nextPlace + space].
  2174. ! !
  2175.  
  2176. !AlignmentMorph methodsFor: 'private' stamp: 'sw 9/10/97 14:54'!
  2177. insertionIndexFor: aMorph
  2178.     "Return the index at which the given morph should be inserted into the submorphs of the receiver."
  2179.  
  2180.     | newCenter |
  2181.     newCenter _ aMorph fullBounds center.
  2182.     orientation == #horizontal ifTrue:
  2183.         [submorphs doWithIndex: [:m :i |
  2184.             newCenter x < m fullBounds center x ifTrue: [^ i]]].
  2185.     orientation == #vertical ifTrue:
  2186.         [submorphs doWithIndex: [:m :i |
  2187.             newCenter y < m fullBounds center y ifTrue: [^ i]]].
  2188.  
  2189.     ^ submorphs size + 1  "insert after the last submorph"
  2190. ! !
  2191.  
  2192. !AlignmentMorph methodsFor: 'private'!
  2193. layoutInWidth: w height: h
  2194.     "Adjust the size of the receiver in its space-filling dimensions during layout. This message is sent to only to layout submorphs."
  2195.  
  2196.     ((hResizing = #spaceFill) and: [bounds width ~= w]) ifTrue: [
  2197.         bounds _ bounds origin extent: (w @ bounds height).
  2198.         fullBounds _ nil.
  2199.         layoutNeeded _ true].
  2200.  
  2201.     ((vResizing = #spaceFill) and: [bounds height ~= h]) ifTrue: [
  2202.         bounds _ bounds origin extent: (bounds width @ h).
  2203.         fullBounds _ nil.
  2204.         layoutNeeded _ true].
  2205. ! !
  2206.  
  2207. !AlignmentMorph methodsFor: 'private' stamp: 'di 5/7/1998 01:21'!
  2208. placeAndSize: m at: nextPlace padding: padding
  2209.  
  2210.     | space totalInset fullBnds left top |
  2211.     totalInset _ inset + borderWidth.
  2212.     orientation = #horizontal ifTrue: [
  2213.         space _ m minWidth max: minCellSize.
  2214.         m isAlignmentMorph ifTrue: [
  2215.             (m hResizing = #spaceFill) ifTrue: [space _ space + padding].
  2216.             m layoutInWidth: space height: (bounds height - (2 * totalInset))].
  2217.     ] ifFalse: [
  2218.         space _ m minHeight max: minCellSize.
  2219.         m isAlignmentMorph ifTrue: [
  2220.             (m vResizing = #spaceFill) ifTrue: [space _ space + padding].
  2221.             m layoutInWidth: (bounds width - (2 * totalInset)) height: space]].
  2222.  
  2223.     fullBnds _ m fullBounds.
  2224.     orientation = #horizontal ifTrue: [
  2225.         left _ nextPlace.
  2226.         centering = #topLeft
  2227.             ifTrue: [top _ bounds top + totalInset].
  2228.         centering = #bottomRight
  2229.             ifTrue: [top _ bounds bottom - totalInset - fullBnds height].
  2230.         centering = #center
  2231.             ifTrue: [top _ bounds top + ((bounds height - fullBnds height) // 2)].
  2232.     ] ifFalse: [
  2233.         top _ nextPlace.
  2234.         centering = #topLeft
  2235.             ifTrue: [left _ bounds left + totalInset].
  2236.         centering = #bottomRight
  2237.             ifTrue: [left _ bounds right - totalInset - fullBnds width].
  2238.         centering = #center
  2239.             ifTrue: [left _ bounds left + ((bounds width - fullBnds width) // 2)]].
  2240.  
  2241.     m position: (left + (m bounds left - fullBnds left)) @ (top + (m bounds top - fullBnds top)).
  2242.     ^ space
  2243. ! !
  2244.  
  2245. !AlignmentMorph methodsFor: 'private' stamp: 'di 5/7/1998 01:21'!
  2246. resizeIfNeeded
  2247.     "Resize this morph if it is space-filling or shrink-wrap and its owner is not a layout morph."
  2248.  
  2249.     | newWidth newHeight |
  2250.     newWidth _ bounds width.
  2251.     newHeight _ bounds height.
  2252.  
  2253.     (owner == nil or: [owner isAlignmentMorph not]) ifTrue: [
  2254.         "if spaceFill and not in a LayoutMorph, grow to enclose submorphs"
  2255.         hResizing = #spaceFill ifTrue: [newWidth _ self minWidth max: self bounds width].
  2256.         vResizing = #spaceFill ifTrue: [newHeight _ self minHeight max: self bounds height]].
  2257.  
  2258.     "if shrinkWrap, adjust size to just fit around submorphs"
  2259.     hResizing = #shrinkWrap ifTrue: [newWidth _ self minWidth].
  2260.     vResizing = #shrinkWrap ifTrue: [newHeight _ self minHeight].
  2261.  
  2262.     ((newWidth ~= bounds width) or: [newHeight ~= bounds height]) ifTrue: [
  2263.         "bounds really changed; flush fullBounds cache and fix submorph layouts"
  2264.         bounds _ bounds origin extent: newWidth@newHeight.
  2265.         fullBounds _ nil].
  2266. ! !
  2267.  
  2268. !AlignmentMorph methodsFor: 'private' stamp: 'sw 5/6/1998 15:58'!
  2269. wantsKeyboardFocusFor: aSubmorph
  2270.     aSubmorph wouldAcceptKeyboardFocus ifTrue: [^ true].
  2271.     ^ super wantsKeyboardFocusFor: aSubmorph! !
  2272.  
  2273. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2274.  
  2275. AlignmentMorph class
  2276.     instanceVariableNames: ''!
  2277.  
  2278. !AlignmentMorph class methodsFor: 'instance creation'!
  2279. newColumn
  2280.  
  2281.     ^ self new
  2282.         orientation: #vertical;
  2283.         hResizing: #spaceFill;
  2284.         vResizing: #spaceFill
  2285. ! !
  2286.  
  2287. !AlignmentMorph class methodsFor: 'instance creation'!
  2288. newRow
  2289.  
  2290.     ^ self new
  2291.         orientation: #horizontal;
  2292.         hResizing: #spaceFill;
  2293.         vResizing: #spaceFill;
  2294.         borderWidth: 0
  2295. ! !
  2296.  
  2297. !AlignmentMorph class methodsFor: 'instance creation' stamp: 'jm 5/4/1998 12:18'!
  2298. newSpacer: aColor
  2299.     "Answer a space-filling instance of me of the given color."
  2300.  
  2301.     ^ self new
  2302.         hResizing: #spaceFill;
  2303.         vResizing: #spaceFill;
  2304.         inset: 0;
  2305.         borderWidth: 0;
  2306.         color: aColor.
  2307. ! !
  2308. Path subclass: #Arc
  2309.     instanceVariableNames: 'quadrant radius center '
  2310.     classVariableNames: ''
  2311.     poolDictionaries: ''
  2312.     category: 'Graphics-Paths'!
  2313. !Arc commentStamp: 'di 5/22/1998 16:32' prior: 0!
  2314. Arc comment:
  2315. 'Arcs are an unusual implementation of splines
  2316. due to Ted Kaehler.  Imagine two lines that meet at a corner.
  2317. Now imagine two moving points; one moves from the corner to
  2318. the end on one line, the other moves from the end of the other
  2319. line in to the corner.  Now imagine a series of lines drawn 
  2320. between those moving points at each step along the way (they
  2321. form a sort of spider web pattern).  By connecting segments
  2322. of the intersecting lines, a smooth curve is achieved that is
  2323. tangent to both of the original lines.  Voila.'!
  2324.  
  2325.  
  2326. !Arc methodsFor: 'accessing'!
  2327. center
  2328.     "Answer the point at the center of the receiver."
  2329.  
  2330.     ^center! !
  2331.  
  2332. !Arc methodsFor: 'accessing'!
  2333. center: aPoint 
  2334.     "Set aPoint to be the receiver's center."
  2335.  
  2336.     center _ aPoint! !
  2337.  
  2338. !Arc methodsFor: 'accessing'!
  2339. center: aPoint radius: anInteger 
  2340.     "The receiver is defined by a point at the center and a radius. The 
  2341.     quadrant is not reset."
  2342.  
  2343.     center _ aPoint.
  2344.     radius _ anInteger! !
  2345.  
  2346. !Arc methodsFor: 'accessing'!
  2347. center: aPoint radius: anInteger quadrant: section 
  2348.     "Set the receiver's quadrant to be the argument, section. The size of the 
  2349.     receiver is defined by the center and its radius."
  2350.  
  2351.     center _ aPoint.
  2352.     radius _ anInteger.
  2353.     quadrant _ section! !
  2354.  
  2355. !Arc methodsFor: 'accessing'!
  2356. quadrant
  2357.     "Answer the part of the circle represented by the receiver."
  2358.     ^quadrant! !
  2359.  
  2360. !Arc methodsFor: 'accessing'!
  2361. quadrant: section 
  2362.     "Set the part of the circle represented by the receiver to be the argument, 
  2363.     section."
  2364.  
  2365.     quadrant _ section! !
  2366.  
  2367. !Arc methodsFor: 'accessing'!
  2368. radius
  2369.     "Answer the receiver's radius."
  2370.  
  2371.     ^radius! !
  2372.  
  2373. !Arc methodsFor: 'accessing'!
  2374. radius: anInteger 
  2375.     "Set the receiver's radius to be the argument, anInteger."
  2376.  
  2377.     radius _ anInteger! !
  2378.  
  2379.  
  2380. !Arc methodsFor: 'display box access'!
  2381. computeBoundingBox
  2382.     | aRectangle aPoint |
  2383.     aRectangle _ center - radius + form offset extent: form extent + (radius * 2) asPoint.
  2384.     aPoint _ center + form extent.
  2385.     quadrant = 1 ifTrue: [^ aRectangle encompass: center x @ aPoint y].
  2386.     quadrant = 2 ifTrue: [^ aRectangle encompass: aPoint x @ aPoint y].
  2387.     quadrant = 3 ifTrue: [^ aRectangle encompass: aPoint x @ center y].
  2388.     quadrant = 4 ifTrue: [^ aRectangle encompass: center x @ center y]! !
  2389.  
  2390.  
  2391. !Arc methodsFor: 'displaying'!
  2392. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
  2393.  
  2394.     | nSegments line angle sin cos xn yn xn1 yn1 |
  2395.     nSegments _ 12.0.
  2396.     line _ Line new.
  2397.     line form: self form.
  2398.     angle _ 90.0 / nSegments.
  2399.     sin _ (angle * (2 * Float pi / 360.0)) sin.
  2400.     cos _ (angle * (2 * Float pi / 360.0)) cos.
  2401.     quadrant = 1
  2402.         ifTrue: 
  2403.             [xn _ radius asFloat.
  2404.             yn _ 0.0].
  2405.     quadrant = 2
  2406.         ifTrue: 
  2407.             [xn _ 0.0.
  2408.             yn _ 0.0 - radius asFloat].
  2409.     quadrant = 3
  2410.         ifTrue: 
  2411.             [xn _ 0.0 - radius asFloat.
  2412.             yn _ 0.0].
  2413.     quadrant = 4
  2414.         ifTrue: 
  2415.             [xn _ 0.0.
  2416.             yn _ radius asFloat].
  2417.     nSegments asInteger
  2418.         timesRepeat: 
  2419.             [xn1 _ xn * cos + (yn * sin).
  2420.             yn1 _ yn * cos - (xn * sin).
  2421.             line beginPoint: center + (xn asInteger @ yn asInteger).
  2422.             line endPoint: center + (xn1 asInteger @ yn1 asInteger).
  2423.             line
  2424.                 displayOn: aDisplayMedium
  2425.                 at: aPoint
  2426.                 clippingBox: clipRect
  2427.                 rule: anInteger
  2428.                 fillColor: aForm.
  2429.             xn _ xn1.
  2430.             yn _ yn1]! !
  2431.  
  2432. !Arc methodsFor: 'displaying'!
  2433. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  2434.  
  2435.     | newArc tempCenter |
  2436.     newArc _ Arc new.
  2437.     tempCenter _ aTransformation applyTo: self center.
  2438.     newArc center: tempCenter x asInteger @ tempCenter y asInteger.
  2439.     newArc quadrant: self quadrant.
  2440.     newArc radius: (self radius * aTransformation scale x) asInteger.
  2441.     newArc form: self form.
  2442.     newArc
  2443.         displayOn: aDisplayMedium
  2444.         at: 0 @ 0
  2445.         clippingBox: clipRect
  2446.         rule: anInteger
  2447.         fillColor: aForm! !
  2448.  
  2449. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2450.  
  2451. Arc class
  2452.     instanceVariableNames: ''!
  2453.  
  2454. !Arc class methodsFor: 'examples'!
  2455. example
  2456.     "Click the button somewhere on the screen. The designated point will
  2457.     be the center of an Arc with radius 50 in the 4th quadrant."
  2458.  
  2459.     | anArc aForm |
  2460.     aForm _ Form extent: 1 @ 30.    "make a long thin Form for display"
  2461.     aForm fillBlack.                        "turn it black"
  2462.     anArc _ Arc new.
  2463.     anArc form: aForm.                    "set the form for display"
  2464.     anArc radius: 50.0.
  2465.     anArc center: Sensor waitButton.
  2466.     anArc quadrant: 4.
  2467.     anArc displayOn: Display.
  2468.     Sensor waitButton
  2469.  
  2470.     "Arc example"! !
  2471. ArrayedCollection variableSubclass: #Array
  2472.     instanceVariableNames: ''
  2473.     classVariableNames: ''
  2474.     poolDictionaries: ''
  2475.     category: 'Collections-Arrayed'!
  2476. !Array commentStamp: 'di 5/22/1998 16:32' prior: 0!
  2477. Array comment:
  2478. 'I present an ArrayedCollection whose elements are objects.'!
  2479.  
  2480.  
  2481. !Array methodsFor: 'comparing'!
  2482. hash
  2483.     "Make sure that equal (=) arrays hash equally."
  2484.  
  2485.     self size = 0 ifTrue: [^17171].
  2486.     ^(self at: 1) hash + (self at: self size) hash! !
  2487.  
  2488. !Array methodsFor: 'comparing'!
  2489. hashMappedBy: map
  2490.     "Answer what my hash would be if oops changed according to map."
  2491.  
  2492.     self size = 0 ifTrue: [^self hash].
  2493.     ^(self first hashMappedBy: map) + (self last hashMappedBy: map)! !
  2494.  
  2495.  
  2496. !Array methodsFor: 'converting'!
  2497. asArray
  2498.     "Answer with the receiver itself."
  2499.  
  2500.     ^self! !
  2501.  
  2502. !Array methodsFor: 'converting'!
  2503. elementsExchangeIdentityWith: otherArray
  2504.     <primitive: 128>
  2505.     self primitiveFailed! !
  2506.  
  2507. !Array methodsFor: 'converting'!
  2508. evalStrings
  2509.        "Allows you to construct literal arrays.
  2510.     #(true false nil '5@6' 'Set new' '''text string''') evalStrings
  2511.     gives an array with true, false, nil, a Point, a Set, and a String
  2512.     instead of just a bunch of Symbols"
  2513.     | it |
  2514.  
  2515.     ^ self collect: [:each |
  2516.         it _ each.
  2517.         each == #true ifTrue: [it _ true].
  2518.               each == #false ifTrue: [it _ false].
  2519.         each == #nil ifTrue: [it _ nil].
  2520.         each class == String ifTrue: [
  2521.             it _ Compiler evaluate: each].
  2522.         each class == Array ifTrue: [it _ it evalStrings].
  2523.         it]! !
  2524.  
  2525.  
  2526. !Array methodsFor: 'printing'!
  2527. isLiteral
  2528.  
  2529.     self detect: [:element | element isLiteral not] ifNone: [^true].
  2530.     ^false! !
  2531.  
  2532. !Array methodsFor: 'printing' stamp: 'di 6/20/97 09:09'!
  2533. printOn: aStream
  2534.     aStream nextPut: $(.
  2535.     self do: [:element | element printOn: aStream. aStream space].
  2536.     aStream nextPut: $)! !
  2537.  
  2538. !Array methodsFor: 'printing'!
  2539. storeOn: aStream 
  2540.     "Use the literal form if possible."
  2541.  
  2542.     self isLiteral
  2543.         ifTrue: 
  2544.             [aStream nextPut: $#; nextPut: $(.
  2545.             self do: 
  2546.                 [:element | 
  2547.                 element printOn: aStream.
  2548.                 aStream space].
  2549.             aStream nextPut: $)]
  2550.         ifFalse: [super storeOn: aStream]! !
  2551.  
  2552.  
  2553. !Array methodsFor: 'private' stamp: 'di 8/15/97 09:55'!
  2554. hasLiteralSuchThat: litBlock
  2555.     "Answer true if litBlock returns true for any literal in this array, even if imbedded in further array structure.  This method is only intended for private use by CompiledMethod hasLiteralSuchThat:"
  2556.     | lit |
  2557.     1 to: self size do:
  2558.         [:index | lit _ self at: index.
  2559.         (litBlock value: lit) ifTrue: [^ true].
  2560.         (lit class == Array and: [lit hasLiteralSuchThat: litBlock]) ifTrue: [^ true]].
  2561.     ^false! !
  2562.  
  2563. !Array methodsFor: 'private'!
  2564. replaceFrom: start to: stop with: replacement startingAt: repStart 
  2565.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  2566.     <primitive: 105>
  2567.     super replaceFrom: start to: stop with: replacement startingAt: repStart! !
  2568. ArrayedCollection subclass: #Array2D
  2569.     instanceVariableNames: 'width contents '
  2570.     classVariableNames: ''
  2571.     poolDictionaries: ''
  2572.     category: 'Collections-Arrayed'!
  2573.  
  2574. !Array2D methodsFor: 'access'!
  2575. at: i at: j
  2576.     "return the element"
  2577.     (i < 1) | (i > width) ifTrue: [
  2578.         ^ self error: 'first index out of bounds'].
  2579.     "second index bounds check is automatic, since contents
  2580.         array will get a bounds error."
  2581.  
  2582.     ^ contents at: (j - 1) * width + i! !
  2583.  
  2584. !Array2D methodsFor: 'access'!
  2585. at: i at: j add: value
  2586.     "add value to the element"
  2587.     | index |
  2588.     (i < 1) | (i > width) ifTrue: [
  2589.         ^ self error: 'first index out of bounds'].
  2590.     "second index bounds check is automatic, since contents
  2591.         array will get a bounds error."
  2592.  
  2593.     index _ (j - 1) * width + i.
  2594.     ^ contents at: index put: (contents at: index) + value! !
  2595.  
  2596. !Array2D methodsFor: 'access'!
  2597. at: i at: j put: value
  2598.     "return the element"
  2599.     (i < 1) | (i > width) ifTrue: [
  2600.         ^ self error: 'first index out of bounds'].
  2601.     "second index bounds check is automatic, since contents
  2602.         array will get a bounds error."
  2603.  
  2604.     ^ contents at: (j - 1) * width + i put: value! !
  2605.  
  2606. !Array2D methodsFor: 'access'!
  2607. atAllPut: value
  2608.     "Initialize"
  2609.     contents atAllPut: value! !
  2610.  
  2611. !Array2D methodsFor: 'access'!
  2612. atCol: i
  2613.     "Fetch a whole column.  6/20/96 tk"
  2614.  
  2615.     | ans |
  2616.     ans _ contents class new: self height.
  2617.     1 to: self height do: [:ind |
  2618.         ans at: ind put: (self at: i at: ind)].
  2619.     ^ ans! !
  2620.  
  2621. !Array2D methodsFor: 'access'!
  2622. atCol: i put: list
  2623.     "Put in a whole column.
  2624.      hold first index constant"
  2625.  
  2626.     list size = self height ifFalse: [self error: 'wrong size'].
  2627.     list doWithIndex: [:value :j |
  2628.         self at: i at: j put: value].! !
  2629.  
  2630. !Array2D methodsFor: 'access'!
  2631. atRow: j
  2632.     "Fetch a whole row.  6/20/96 tk"
  2633.  
  2634.     ^ contents copyFrom: (j - 1) * width + 1 to: (j) * width! !
  2635.  
  2636. !Array2D methodsFor: 'access'!
  2637. atRow: j put: list
  2638.     "Put in a whole row.
  2639.      hold second index constant"
  2640.  
  2641.     list size = self width ifFalse: [self error: 'wrong size'].
  2642.     list doWithIndex: [:value :i |
  2643.         self at: i at: j put: value].! !
  2644.  
  2645. !Array2D methodsFor: 'access'!
  2646. do: aBlock
  2647.     "Iterate with X varying most quickly.  6/20/96 tk"
  2648.     ^ contents do: aBlock! !
  2649.  
  2650. !Array2D methodsFor: 'access'!
  2651. extent
  2652.     ^ width @ self height! !
  2653.  
  2654. !Array2D methodsFor: 'access'!
  2655. extent: extent fromArray: anArray
  2656.     "Load this 2-D array up from a 1-D array.  X varies most quickly.  6/20/96 tk"
  2657.  
  2658.     extent x * extent y = anArray size ifFalse: [
  2659.         ^ self error: 'dimensions don''t match'].
  2660.     width _ extent x.
  2661.     contents _ anArray.! !
  2662.  
  2663. !Array2D methodsFor: 'access'!
  2664. height
  2665.     "second dimension"
  2666.     "no need to save it"
  2667.     ^ contents size // width! !
  2668.  
  2669. !Array2D methodsFor: 'access'!
  2670. width
  2671.     "first dimension"
  2672.     ^ width! !
  2673.  
  2674. !Array2D methodsFor: 'access'!
  2675. width: x height: y type: class
  2676.     "Set the number of elements in the first and
  2677.     second dimensions.  class can be Array or String or ByteArray."
  2678.  
  2679.     contents == nil ifFalse: [self error: 'No runtime size change yet'].
  2680.         "later move all the elements to the new sized array"
  2681.     width _ x.
  2682.     contents _ class new: width*y.! !
  2683.  
  2684. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2685.  
  2686. Array2D class
  2687.     instanceVariableNames: ''!
  2688.  
  2689. !Array2D class methodsFor: 'as yet unclassified'!
  2690. new
  2691.     "Override ArrayedCollection.  6/20/96 tk"
  2692.     ^ self basicNew! !
  2693.  
  2694. !Array2D class methodsFor: 'as yet unclassified'!
  2695. new: size
  2696.     "Use (self new width: x height: y type: Array)   6/20/96 tk"
  2697.     ^ self shouldNotImplement! !
  2698. SequenceableCollection subclass: #ArrayedCollection
  2699.     instanceVariableNames: ''
  2700.     classVariableNames: ''
  2701.     poolDictionaries: ''
  2702.     category: 'Collections-Abstract'!
  2703. !ArrayedCollection commentStamp: 'di 5/22/1998 16:32' prior: 0!
  2704. ArrayedCollection comment:
  2705. 'I am an abstract collection of elements with a fixed range of integers (from 1 to n>=1) as external keys.'!
  2706.  
  2707.  
  2708. !ArrayedCollection methodsFor: 'accessing'!
  2709. size
  2710.     "Primitive. Answer the number of indexable fields in the receiver. This
  2711.     value is the same as the largest legal subscript. Primitive is specified
  2712.     here to override SequenceableCollection size. Essential. See Object
  2713.     documentation whatIsAPrimitive. "
  2714.  
  2715.     <primitive: 62>
  2716.     ^self basicSize! !
  2717.  
  2718.  
  2719. !ArrayedCollection methodsFor: 'adding'!
  2720. add: newObject
  2721.  
  2722.     self shouldNotImplement! !
  2723.  
  2724.  
  2725. !ArrayedCollection methodsFor: 'printing'!
  2726. storeOn: aStream
  2727.  
  2728.     aStream nextPutAll: '(('.
  2729.     aStream nextPutAll: self class name.
  2730.     aStream nextPutAll: ' new: '.
  2731.     aStream store: self size.
  2732.     aStream nextPut: $).
  2733.     (self storeElementsFrom: 1 to: self size on: aStream)
  2734.         ifFalse: [aStream nextPutAll: '; yourself'].
  2735.     aStream nextPut: $)! !
  2736.  
  2737.  
  2738. !ArrayedCollection methodsFor: 'private'!
  2739. defaultElement
  2740.  
  2741.     ^nil! !
  2742.  
  2743. !ArrayedCollection methodsFor: 'private'!
  2744. fill: numElements fromStack: aContext 
  2745.     "Fill me with numElements elements, popped in reverse order from
  2746.      the stack of aContext.  Do not call directly: this is called indirectly by {1. 2. 3}
  2747.      constructs."
  2748.  
  2749.     aContext pop: numElements toIndexable: self! !
  2750.  
  2751. !ArrayedCollection methodsFor: 'private'!
  2752. storeElementsFrom: firstIndex to: lastIndex on: aStream
  2753.  
  2754.     | noneYet defaultElement arrayElement |
  2755.     noneYet _ true.
  2756.     defaultElement _ self defaultElement.
  2757.     firstIndex to: lastIndex do: 
  2758.         [:index | 
  2759.         arrayElement _ self at: index.
  2760.         arrayElement = defaultElement
  2761.             ifFalse: 
  2762.                 [noneYet
  2763.                     ifTrue: [noneYet _ false]
  2764.                     ifFalse: [aStream nextPut: $;].
  2765.                 aStream nextPutAll: ' at: '.
  2766.                 aStream store: index.
  2767.                 aStream nextPutAll: ' put: '.
  2768.                 aStream store: arrayElement]].
  2769.     ^noneYet! !
  2770.  
  2771. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  2772.  
  2773. ArrayedCollection class
  2774.     instanceVariableNames: ''!
  2775.  
  2776. !ArrayedCollection class methodsFor: 'instance creation'!
  2777. fromBraceStack: itsSize 
  2778.     "Answer an instance of me with itsSize elements, popped in reverse order from
  2779.      the stack of thisContext sender.  Do not call directly: this is called by {1. 2. 3}
  2780.      constructs."
  2781.  
  2782.     ^ (self new: itsSize) fill: itsSize fromStack: thisContext sender! !
  2783.  
  2784. !ArrayedCollection class methodsFor: 'instance creation'!
  2785. new
  2786.     "Answer a new instance of me, with size = 0."
  2787.  
  2788.     ^self new: 0! !
  2789.  
  2790. !ArrayedCollection class methodsFor: 'instance creation'!
  2791. new: size withAll: value 
  2792.     "Answer an instance of me, with number of elements equal to size, each 
  2793.     of which refers to the argument, value."
  2794.  
  2795.     ^(self new: size) atAllPut: value! !
  2796.  
  2797. !ArrayedCollection class methodsFor: 'instance creation'!
  2798. newFrom: aCollection 
  2799.     "Answer an instance of me containing the same elements as aCollection."
  2800.     | newArray |
  2801.     newArray _ self new: aCollection size.
  2802.     1 to: aCollection size do: [:i | newArray at: i put: (aCollection at: i)].
  2803.     ^ newArray
  2804.  
  2805. "    Array newFrom: {1. 2. 3}
  2806.     {1. 2. 3} as: Array
  2807.     {1. 2. 3} as: ByteArray
  2808.     {$c. $h. $r} as: String
  2809.     {$c. $h. $r} as: Text
  2810. "! !
  2811.  
  2812. !ArrayedCollection class methodsFor: 'instance creation'!
  2813. with: anObject 
  2814.     "Answer a new instance of me, containing only anObject."
  2815.  
  2816.     | newCollection |
  2817.     newCollection _ self new: 1.
  2818.     newCollection at: 1 put: anObject.
  2819.     ^newCollection! !
  2820.  
  2821. !ArrayedCollection class methodsFor: 'instance creation'!
  2822. with: firstObject with: secondObject 
  2823.     "Answer a new instance of me, containing firstObject and secondObject."
  2824.  
  2825.     | newCollection |
  2826.     newCollection _ self new: 2.
  2827.     newCollection at: 1 put: firstObject.
  2828.     newCollection at: 2 put: secondObject.
  2829.     ^newCollection! !
  2830.  
  2831. !ArrayedCollection class methodsFor: 'instance creation'!
  2832. with: firstObject with: secondObject with: thirdObject 
  2833.     "Answer a new instance of me, containing only the three arguments as
  2834.     elements."
  2835.  
  2836.     | newCollection |
  2837.     newCollection _ self new: 3.
  2838.     newCollection at: 1 put: firstObject.
  2839.     newCollection at: 2 put: secondObject.
  2840.     newCollection at: 3 put: thirdObject.
  2841.     ^newCollection! !
  2842.  
  2843. !ArrayedCollection class methodsFor: 'instance creation'!
  2844. with: firstObject with: secondObject with: thirdObject with: fourthObject 
  2845.     "Answer a new instance of me, containing only the three arguments as
  2846.     elements."
  2847.  
  2848.     | newCollection |
  2849.     newCollection _ self new: 4.
  2850.     newCollection at: 1 put: firstObject.
  2851.     newCollection at: 2 put: secondObject.
  2852.     newCollection at: 3 put: thirdObject.
  2853.     newCollection at: 4 put: fourthObject.
  2854.     ^newCollection! !
  2855.  
  2856. !ArrayedCollection class methodsFor: 'instance creation'!
  2857. with: firstObject with: secondObject with: thirdObject with: fourthObject with: fifthObject
  2858.     "Answer a new instance of me, containing only the five arguments as
  2859.     elements."
  2860.  
  2861.     | newCollection |
  2862.     newCollection _ self new: 5.
  2863.     newCollection at: 1 put: firstObject.
  2864.     newCollection at: 2 put: secondObject.
  2865.     newCollection at: 3 put: thirdObject.
  2866.     newCollection at: 4 put: fourthObject.
  2867.     newCollection at: 5 put: fifthObject.
  2868.     ^newCollection! !
  2869. ParseNode subclass: #AssignmentNode
  2870.     instanceVariableNames: 'variable value '
  2871.     classVariableNames: ''
  2872.     poolDictionaries: ''
  2873.     category: 'System-Compiler'!
  2874. !AssignmentNode commentStamp: 'di 5/22/1998 16:32' prior: 0!
  2875. AssignmentNode comment: 'I represent a (var_expr) construct.'!
  2876.  
  2877.  
  2878. !AssignmentNode methodsFor: 'initialize-release'!
  2879. toDoIncrement: var
  2880.     var = variable ifFalse: [^ nil].
  2881.     (value isMemberOf: MessageNode) 
  2882.         ifTrue: [^ value toDoIncrement: var]
  2883.         ifFalse: [^ nil]! !
  2884.  
  2885. !AssignmentNode methodsFor: 'initialize-release'!
  2886. value
  2887.     ^ value! !
  2888.  
  2889. !AssignmentNode methodsFor: 'initialize-release'!
  2890. variable: aVariable value: expression
  2891.  
  2892.     variable _ aVariable.
  2893.     value _ expression! !
  2894.  
  2895. !AssignmentNode methodsFor: 'initialize-release'!
  2896. variable: aVariable value: expression from: encoder
  2897.  
  2898.     (aVariable isMemberOf: MessageNode)
  2899.         ifTrue: [^aVariable store: expression from: encoder].
  2900.     variable _ aVariable.
  2901.     value _ expression! !
  2902.  
  2903.  
  2904. !AssignmentNode methodsFor: 'code generation'!
  2905. emitForEffect: stack on: aStream
  2906.  
  2907.     value emitForValue: stack on: aStream.
  2908.     variable emitStorePop: stack on: aStream! !
  2909.  
  2910. !AssignmentNode methodsFor: 'code generation'!
  2911. emitForValue: stack on: aStream
  2912.  
  2913.     value emitForValue: stack on: aStream.
  2914.     variable emitStore: stack on: aStream! !
  2915.  
  2916. !AssignmentNode methodsFor: 'code generation'!
  2917. sizeForEffect: encoder
  2918.  
  2919.     ^(value sizeForValue: encoder)
  2920.         + (variable sizeForStorePop: encoder)! !
  2921.  
  2922. !AssignmentNode methodsFor: 'code generation'!
  2923. sizeForValue: encoder
  2924.  
  2925.     ^(value sizeForValue: encoder)
  2926.         + (variable sizeForStore: encoder)! !
  2927.  
  2928.  
  2929. !AssignmentNode methodsFor: 'printing'!
  2930. printOn: aStream indent: level
  2931.  
  2932.     variable printOn: aStream indent: level.
  2933.     aStream nextPutAll: ' _ '.
  2934.     value printOn: aStream indent: level + 2! !
  2935.  
  2936. !AssignmentNode methodsFor: 'printing'!
  2937. printOn: aStream indent: level precedence: p
  2938.  
  2939.     p < 4 ifTrue: [aStream nextPutAll: '('].
  2940.     self printOn: aStream indent: level.
  2941.     p < 4 ifTrue: [aStream nextPutAll: ')']! !
  2942.  
  2943.  
  2944. !AssignmentNode methodsFor: 'equation translation'!
  2945. variable
  2946.     ^variable! !
  2947.  
  2948.  
  2949. !AssignmentNode methodsFor: 'C translation'!
  2950. asTranslatorNode
  2951.     ^TAssignmentNode new
  2952.         setVariable: variable asTranslatorNode
  2953.         expression: value asTranslatorNode! !
  2954. TileMorph subclass: #AssignmentTileMorph
  2955.     instanceVariableNames: 'assignmentRoot assignmentSuffix dataType '
  2956.     classVariableNames: ''
  2957.     poolDictionaries: ''
  2958.     category: 'Morphic-Scripting-Tiles'!
  2959.  
  2960. !AssignmentTileMorph methodsFor: 'all' stamp: 'sw 12/12/97 01:24'!
  2961. arrowAction: delta
  2962.     | index aList |
  2963.     owner ifNil: [^ self].
  2964.     operatorOrExpression ifNotNil:
  2965.         [aList _ #(: Incr: Decr: Mult:).
  2966.         index _ aList indexOf: assignmentSuffix asSymbol.
  2967.         index  > 0 ifTrue:
  2968.             [self setAssignmentSuffix: (aList atWrap: index + delta).
  2969.             self acceptNewLiteral]]! !
  2970.  
  2971. !AssignmentTileMorph methodsFor: 'all' stamp: 'sw 5/2/1998 15:00'!
  2972. computeOperatorOrExpression
  2973.     | aSuffix |
  2974.     operatorOrExpression _ (assignmentRoot, assignmentSuffix) asSymbol.
  2975.     aSuffix _ ScriptingSystem wordingForAssignmentSuffix: assignmentSuffix.
  2976.     operatorReadoutString _ assignmentRoot, ' ', aSuffix.
  2977.      self line1: operatorReadoutString.
  2978.     dataType == #number ifTrue: [self addArrows] ! !
  2979.  
  2980. !AssignmentTileMorph methodsFor: 'all' stamp: 'sw 11/17/97 14:36'!
  2981. initialize
  2982.     super initialize.
  2983.     type _ #operator.
  2984.     assignmentSuffix _ ':'! !
  2985.  
  2986. !AssignmentTileMorph methodsFor: 'all' stamp: 'sw 5/2/1998 15:00'!
  2987. setAssignmentSuffix: aString
  2988.     assignmentSuffix _ aString.
  2989.     self computeOperatorOrExpression.
  2990.     type _ #operator.
  2991.      self line1: (ScriptingSystem wordingForOperator: operatorOrExpression).
  2992.     self addArrows; updateLiteralLabel! !
  2993.  
  2994. !AssignmentTileMorph methodsFor: 'all' stamp: 'sw 2/16/98 01:12'!
  2995. setRoot: aString dataType: aSymbol
  2996.     assignmentRoot _ aString.
  2997.     assignmentSuffix _ ':'.
  2998.     dataType _ aSymbol.
  2999.     self updateLiteralLabel! !
  3000.  
  3001. !AssignmentTileMorph methodsFor: 'all' stamp: 'sw 1/31/98 00:42'!
  3002. storeCodeOn: aStream
  3003.     aStream nextPutAll: ' assign', (assignmentSuffix copyWithout: $:), 'Getter: #'.
  3004.     aStream nextPutAll: (Utilities getterSelectorFor: assignmentRoot).
  3005.     aStream nextPutAll: ' setter: #'.
  3006.     aStream nextPutAll: (Utilities setterSelectorFor: assignmentRoot).
  3007.     aStream nextPutAll: ' amt: '! !
  3008.  
  3009. !AssignmentTileMorph methodsFor: 'all' stamp: 'sw 1/31/98 00:42'!
  3010. updateLiteralLabel
  3011.     self computeOperatorOrExpression.
  3012.     super updateLiteralLabel! !
  3013. LookupKey subclass: #Association
  3014.     instanceVariableNames: 'value '
  3015.     classVariableNames: ''
  3016.     poolDictionaries: ''
  3017.     category: 'Collections-Support'!
  3018. !Association commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3019. Association comment:
  3020. 'I represent a pair of associated objects--a key and a value. My instances can serve as entries in a dictionary.'!
  3021.  
  3022.  
  3023. !Association methodsFor: 'accessing'!
  3024. key: aKey value: anObject 
  3025.     "Store the arguments as the variables of the receiver."
  3026.  
  3027.     key _ aKey.
  3028.     value _ anObject! !
  3029.  
  3030. !Association methodsFor: 'accessing'!
  3031. value
  3032.     "Answer the value of the receiver."
  3033.  
  3034.     ^value! !
  3035.  
  3036. !Association methodsFor: 'accessing'!
  3037. value: anObject 
  3038.     "Store the argument, anObject, as the value of the receiver."
  3039.  
  3040.     value _ anObject! !
  3041.  
  3042.  
  3043. !Association methodsFor: 'printing'!
  3044. printOn: aStream
  3045.  
  3046.     super printOn: aStream.
  3047.     aStream nextPutAll: '->'.
  3048.     value printOn: aStream! !
  3049.  
  3050. !Association methodsFor: 'printing'!
  3051. storeOn: aStream
  3052.     "Store in the format (key->value)"
  3053.     aStream nextPut: $(.
  3054.     key storeOn: aStream.
  3055.     aStream nextPutAll: '->'.
  3056.     value storeOn: aStream.
  3057.     aStream nextPut: $)! !
  3058.  
  3059. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3060.  
  3061. Association class
  3062.     instanceVariableNames: ''!
  3063.  
  3064. !Association class methodsFor: 'instance creation'!
  3065. key: newKey value: newValue
  3066.     "Answer an instance of me with the arguments as the key and value of 
  3067.     the association."
  3068.  
  3069.     ^(super key: newKey) value: newValue! !
  3070. EllipseMorph subclass: #AtomMorph
  3071.     instanceVariableNames: 'velocity '
  3072.     classVariableNames: ''
  3073.     poolDictionaries: ''
  3074.     category: 'Morphic-Demo'!
  3075.  
  3076. !AtomMorph methodsFor: 'all'!
  3077. bounceIn: aRect
  3078.     | p vx vy px py |
  3079.     p _ self position.
  3080.     vx _ velocity x.  vy _ velocity y.
  3081.     px _ p x + vx.  py _ p y + vy.
  3082.     px > aRect right ifTrue: [
  3083.         px _ aRect right - (px - aRect right).
  3084.         vx _ velocity x negated.
  3085.     ].
  3086.     py > aRect bottom ifTrue: [
  3087.         py _  aRect bottom - (py - aRect bottom).
  3088.         vy _ velocity y negated.
  3089.     ].
  3090.     px < aRect left ifTrue: [
  3091.         px _ aRect left - (px - aRect left).
  3092.         vx _ velocity x negated.
  3093.     ].
  3094.     py < aRect top ifTrue: [
  3095.         py _  aRect top - (py - aRect top).
  3096.         vy _ velocity y negated.
  3097.     ].
  3098.     self position: px @ py.
  3099.     self velocity: vx @ vy.
  3100. ! !
  3101.  
  3102. !AtomMorph methodsFor: 'all'!
  3103. drawOn: aCanvas
  3104.     "Note: Set 'drawAsRect' to true to make the atoms draw faster. When testing the speed of other aspects of Morphic, such as its damage handling efficiency for large numbers of atoms, it is useful to make drawing faster."
  3105.  
  3106.     | drawAsRect |
  3107.     drawAsRect _ false.  "rectangles are faster to draw"
  3108.     drawAsRect
  3109.         ifTrue: [aCanvas fillRectangle: self bounds color: color]
  3110.         ifFalse: [super drawOn: aCanvas].! !
  3111.  
  3112. !AtomMorph methodsFor: 'all'!
  3113. infected
  3114.  
  3115.     ^ color = Color red! !
  3116.  
  3117. !AtomMorph methodsFor: 'all'!
  3118. infected: aBoolean
  3119.  
  3120.     aBoolean
  3121.         ifTrue: [self color: Color red]
  3122.         ifFalse: [self color: Color blue].! !
  3123.  
  3124. !AtomMorph methodsFor: 'all'!
  3125. initialize
  3126.     "Make a new atom with a random position and velocity."
  3127.  
  3128.     super initialize.
  3129.     self extent: 8@7.
  3130.     self color: Color blue.
  3131.     self borderWidth: 0.
  3132.     self randomPositionIn: (0@0 corner: 300@300) maxVelocity: 10.
  3133. ! !
  3134.  
  3135. !AtomMorph methodsFor: 'all'!
  3136. randomPositionIn: aRectangle maxVelocity: maxVelocity
  3137.     "Give this atom a random position and velocity."
  3138.  
  3139.     | origin extent |
  3140.     origin _ aRectangle origin.
  3141.     extent _ aRectangle extent - self bounds extent.
  3142.     self position:
  3143.         (origin x + extent x atRandom) @
  3144.         (origin y + extent y atRandom).
  3145.     velocity _
  3146.         (maxVelocity - (2 * maxVelocity) atRandom) @
  3147.         (maxVelocity - (2 * maxVelocity) atRandom).
  3148. ! !
  3149.  
  3150. !AtomMorph methodsFor: 'all'!
  3151. velocity
  3152.  
  3153.     ^ velocity! !
  3154.  
  3155. !AtomMorph methodsFor: 'all'!
  3156. velocity: newVelocity
  3157.  
  3158.     velocity _ newVelocity.! !
  3159.  
  3160. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3161.  
  3162. AtomMorph class
  3163.     instanceVariableNames: ''!
  3164.  
  3165. !AtomMorph class methodsFor: 'all' stamp: 'di 6/22/97 09:07'!
  3166. includeInNewMorphMenu
  3167.     "Not to be instantiated from the menu"
  3168.     ^ false! !
  3169. EmbeddedServerAction subclass: #AuthorizedServerAction
  3170.     instanceVariableNames: 'authorizer '
  3171.     classVariableNames: ''
  3172.     poolDictionaries: ''
  3173.     category: 'PluggableWebServer'!
  3174. !AuthorizedServerAction commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3175. An EmbeddedServerAction that also has an Authorizer to verify username and password.!
  3176.  
  3177.  
  3178. !AuthorizedServerAction methodsFor: 'URL processing' stamp: 'mjg 11/17/97 11:20'!
  3179. authorizer
  3180.     ^authorizer! !
  3181.  
  3182. !AuthorizedServerAction methodsFor: 'URL processing' stamp: 'mjg 11/17/97 11:20'!
  3183. authorizer: anAuthorizer
  3184.     authorizer _ anAuthorizer
  3185. ! !
  3186.  
  3187. !AuthorizedServerAction methodsFor: 'URL processing' stamp: 'mjg 11/17/97 13:09'!
  3188. checkAuthorization: request
  3189.     ^authorizer user: request userID.
  3190. ! !
  3191.  
  3192. !AuthorizedServerAction methodsFor: 'URL processing' stamp: 'tk 5/21/1998 16:46'!
  3193. mapName: nameString password: pwdString to: aPerson
  3194.     "Insert/remove the username:password combination into/from the users Dictionary.  *** Use this method to add or delete users!!  If you ask for the authorizer and talk to it, the change will not be recorded on the disk!! ***   We use encoding per RFC1421."
  3195.  
  3196.     authorizer mapName: nameString password: pwdString to: aPerson.
  3197.     self authorizer: authorizer.    "force it to be written to the disk"
  3198.         "*** Authorizer not saved to disk yet for this class ***"! !
  3199. SwikiAction subclass: #AuthorizedSwikiAction
  3200.     instanceVariableNames: 'authorizer '
  3201.     classVariableNames: ''
  3202.     poolDictionaries: ''
  3203.     category: 'PluggableWebServer'!
  3204. !AuthorizedSwikiAction commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3205. A Server with a login name and password for the entire Swiki area.  Can be multiple users each with a different password.  Each sees and can modify the whole Swiki area.
  3206.  
  3207. To restart an existing Authorized Swiki:
  3208.  
  3209.     AuthorizedSwikiAction new restore: 'SWSecure'.
  3210.  
  3211. The front page URL is:  http://serverMachine:80/SWSecure.1
  3212.  
  3213. To make a completely new one:
  3214.     | a s |
  3215.     a := Authorizer new.
  3216.     a realm: 'SwikiArea'.
  3217.     a mapName: 'viki' password: 'hard2guess' to: 'viki'.
  3218.     AuthorizedSwikiAction setUp: 'SWSecure'.
  3219.     s := AuthorizedSwikiAction new restore: 'SWSecure'.
  3220.     s authorizer: a.
  3221. !
  3222.  
  3223.  
  3224. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'rp 4/29/98 16:57'!
  3225. authorizer
  3226.     ^authorizer! !
  3227.  
  3228. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'tk 5/22/1998 07:46'!
  3229. authorizer: anAuthorizer
  3230.     "Smash all old name/password pairs with this new set.  Overwrites the file on the disk"
  3231.  
  3232.     | fName refStream |
  3233.     authorizer _ anAuthorizer.
  3234.     fName _ ServerAction serverDirectory, name, (ServerAction pathSeparator), 
  3235.                 'authorizer'.
  3236.     refStream _ SmartRefStream fileNamed: fName.
  3237.     refStream nextPut: authorizer; close.
  3238. ! !
  3239.  
  3240. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'rp 4/29/98 16:58'!
  3241. checkAuthorization: request
  3242.     ^authorizer user: request userID.
  3243. ! !
  3244.  
  3245. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'tk 5/21/1998 16:30'!
  3246. mapName: nameString password: pwdString to: aPerson
  3247.     "Insert/remove the username:password combination into/from the users Dictionary.  *** Use this method to add or delete users!!  If you ask for the authorizer and talk to it, the change will not be recorded on the disk!! ***   We use encoding per RFC1421."
  3248.  
  3249.     authorizer mapName: nameString password: pwdString to: aPerson.
  3250.     self authorizer: authorizer.    "force it to be written to the disk"! !
  3251.  
  3252. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'rp 4/29/98 17:02'!
  3253. process: request
  3254.     self checkAuthorization: request.
  3255.     ^(super process: request).! !
  3256.  
  3257. !AuthorizedSwikiAction methodsFor: 'URL processing' stamp: 'tk 5/22/1998 10:21'!
  3258. restore: nameOfSwiki
  3259.     "Read all files in the directory 'nameOfSwiki'.  Reconstruct the url map."
  3260.  
  3261.     | fName |
  3262.     super restore: nameOfSwiki.
  3263.     fName _ ServerAction serverDirectory, name, (ServerAction pathSeparator), 
  3264.                 'authorizer'.
  3265.     authorizer _ (FileStream oldFileNamed: fName) fileInObjectAndCode.
  3266. ! !
  3267. Object subclass: #Authorizer
  3268.     instanceVariableNames: 'users realm '
  3269.     classVariableNames: ''
  3270.     poolDictionaries: ''
  3271.     category: 'PluggableWebServer'!
  3272. !Authorizer commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3273. The Authorizer does user authorization checking. Each instance of authorizer keeps track of the realm that it is authorizing for, and the table of authorized users. An authorizer can be asked to return the user name/symbol associated with a userID (which concatenates the username and password from the HTTP request) with the user: method.
  3274. !
  3275.  
  3276.  
  3277. !Authorizer methodsFor: 'realms' stamp: 'mjg 11/3/97 12:33'!
  3278. realm
  3279.     ^realm! !
  3280.  
  3281. !Authorizer methodsFor: 'realms' stamp: 'mjg 11/3/97 12:33'!
  3282. realm: aString
  3283.     realm := aString
  3284. ! !
  3285.  
  3286.  
  3287. !Authorizer methodsFor: 'authentication' stamp: 'mjg 11/3/97 13:01'!
  3288. encode: nameString password: pwdString
  3289.     "Encode per RFC1421 of the username:password combination."
  3290.  
  3291.     | clear code clearSize idx map |
  3292.     clear := (nameString, ':', pwdString) asByteArray.
  3293.     clearSize := clear size.
  3294.     [ clear size \\ 3 ~= 0 ] whileTrue: [ clear := clear, #(0) ].
  3295.     idx := 1.
  3296.     map := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.
  3297.     code := WriteStream on: ''.
  3298.     [ idx < clear size ] whileTrue: [ code 
  3299.         nextPut: (map at: (clear at: idx) // 4 + 1);
  3300.         nextPut: (map at: (clear at: idx) \\ 4 * 16 + ((clear at: idx + 1) // 16) + 1);
  3301.            nextPut: (map at: (clear at: idx + 1) \\ 16 * 4 + ((clear at: idx + 2) // 64) + 1);
  3302.            nextPut: (map at: (clear at: idx + 2) \\ 64 + 1).
  3303.         idx := idx + 3 ].
  3304.     code := code contents.
  3305.     idx := code size.
  3306.     clear size - clearSize timesRepeat: [ code at: idx put: $=. idx := idx - 1].
  3307.     ^code! !
  3308.  
  3309. !Authorizer methodsFor: 'authentication' stamp: 'mjg 11/3/97 12:31'!
  3310. mapFrom: aKey to: aPerson
  3311.     "Establish a mapping from a RFC 1421 key to a user."
  3312.  
  3313.     users isNil ifTrue: [ users := Dictionary new ].
  3314.     aPerson
  3315.      isNil ifTrue: [ users removeKey: aKey ]
  3316.      ifFalse: [
  3317.         users removeKey: (users keyAtValue: aPerson ifAbsent: []) ifAbsent: [].
  3318.         users at: aKey put: aPerson ]
  3319. ! !
  3320.  
  3321. !Authorizer methodsFor: 'authentication' stamp: 'tk 5/21/1998 16:32'!
  3322. mapName: nameString password: pwdString to: aPerson
  3323.     "Insert/remove the encoding per RFC1421 of the username:password combination into/from the UserMap.  DO NOT call this directly, use mapName:password:to: in your ServerAction class.  Only it knows how to record the change on the disk!!"
  3324.  
  3325.     self mapFrom: (self encode: nameString password: pwdString) to: aPerson
  3326. ! !
  3327.  
  3328. !Authorizer methodsFor: 'authentication' stamp: 'mjg 11/17/97 13:07'!
  3329. user: userId
  3330.     "Return the requesting user."
  3331.     ^users at: userId ifAbsent: [ self error: (PWS unauthorizedFor: realm) ]! !
  3332. Morph subclass: #BackgroundMorph
  3333.     instanceVariableNames: 'image offset delta running '
  3334.     classVariableNames: ''
  3335.     poolDictionaries: ''
  3336.     category: 'Morphic-Widgets'!
  3337. !BackgroundMorph commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3338. BackgroundMorph comment:
  3339. 'This morph incorporates tiling and regular motion with the intent of supporting, eg, panning of endless (toroidal) backgrounds.
  3340.  
  3341. The idea is that embedded morphs get displayed at a moving offset relative to my position.  Moreover this display is tiled according to the bounding box of the submorphs (subBounds), as much as necesary to fill the rest of my bounds.'!
  3342.  
  3343.  
  3344. !BackgroundMorph methodsFor: 'all' stamp: 'di 11/4/97 09:01'!
  3345. addCustomMenuItems: aCustomMenu hand: aHandMorph
  3346.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  3347.     running
  3348.         ifTrue: [aCustomMenu add: 'stop' action: #stopRunning]
  3349.         ifFalse: [aCustomMenu add: 'start' action: #startRunning].
  3350. ! !
  3351.  
  3352. !BackgroundMorph methodsFor: 'all'!
  3353. drawOn: aCanvas
  3354.     "The tiling is solely determined by bounds, subBounds and offset.
  3355.     The extent of display is determined by bounds and the clipRect of the canvas."
  3356.     | start tileCanvas d subBnds |
  3357.     submorphs isEmpty ifTrue: [^ super drawOn: aCanvas].
  3358.     subBnds _ self subBounds.
  3359.     running ifFalse:
  3360.         [super drawOn: aCanvas.
  3361.         ^ aCanvas fillRectangle: subBnds color: Color lightBlue].
  3362.     start _ subBnds topLeft + offset - bounds topLeft - (1@1) \\ subBnds extent - subBnds extent + (1@1).
  3363.     d _ subBnds topLeft - bounds topLeft.
  3364. "Sensor redButtonPressed ifTrue: [self halt]."
  3365.     start x to: bounds width - 1 by: subBnds width do:
  3366.         [:x |
  3367.         start y to: bounds height - 1 by: subBnds height do:
  3368.             [:y | tileCanvas _ aCanvas copyOffset: (x@y) - d clipRect: bounds.
  3369.             submorphs reverseDo: [:m | m fullDrawOn: tileCanvas]]]! !
  3370.  
  3371. !BackgroundMorph methodsFor: 'all'!
  3372. fullBounds
  3373.     ^ self bounds! !
  3374.  
  3375. !BackgroundMorph methodsFor: 'all'!
  3376. fullDrawOn: aCanvas
  3377.  
  3378.     running ifFalse: [^ super fullDrawOn: (aCanvas copyClipRect: (bounds translateBy: aCanvas origin))].
  3379.     (aCanvas isVisible: bounds) ifTrue: [self drawOn: aCanvas].
  3380. ! !
  3381.  
  3382. !BackgroundMorph methodsFor: 'all'!
  3383. initialize
  3384.     super initialize.
  3385.     offset _ 0@0.
  3386.     delta _ 1@0.
  3387.     running _ true! !
  3388.  
  3389. !BackgroundMorph methodsFor: 'all'!
  3390. layoutChanged
  3391.     "Do nothing, since I clip my submorphs"! !
  3392.  
  3393. !BackgroundMorph methodsFor: 'all'!
  3394. rootForGrabOf: aMorph
  3395.     "Be sticky."
  3396.  
  3397.     ^ nil
  3398. ! !
  3399.  
  3400. !BackgroundMorph methodsFor: 'all'!
  3401. slideBy: inc
  3402.     submorphs isEmpty ifTrue: [^ self].
  3403.     offset _ offset + inc \\ self subBounds extent.
  3404.     self changed! !
  3405.  
  3406. !BackgroundMorph methodsFor: 'all'!
  3407. startRunning
  3408.     running _ true.
  3409.     self changed! !
  3410.  
  3411. !BackgroundMorph methodsFor: 'all'!
  3412. step
  3413.     "Answer the desired time between steps in milliseconds."
  3414.     running ifTrue: [self slideBy: delta]! !
  3415.  
  3416. !BackgroundMorph methodsFor: 'all'!
  3417. stepTime
  3418.     "Answer the desired time between steps in milliseconds."
  3419.  
  3420.     ^ 20! !
  3421.  
  3422. !BackgroundMorph methodsFor: 'all'!
  3423. stopRunning
  3424.     running _ false.
  3425.     self changed! !
  3426.  
  3427. !BackgroundMorph methodsFor: 'all'!
  3428. subBounds
  3429.     "calculate the submorph bounds"
  3430.     | subBounds |
  3431.     subBounds _ nil.
  3432.     self submorphsDo:
  3433.         [:m | subBounds == nil
  3434.             ifTrue: [subBounds _ m fullBounds]
  3435.             ifFalse: [subBounds _ subBounds merge: m fullBounds]].
  3436.     ^ subBounds! !
  3437.  
  3438. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3439.  
  3440. BackgroundMorph class
  3441.     instanceVariableNames: ''!
  3442.  
  3443. !BackgroundMorph class methodsFor: 'all'!
  3444. test
  3445.     ^ self new image: Form fromUser! !
  3446. Collection subclass: #Bag
  3447.     instanceVariableNames: 'contents '
  3448.     classVariableNames: ''
  3449.     poolDictionaries: ''
  3450.     category: 'Collections-Unordered'!
  3451. !Bag commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3452. Bag comment:
  3453. 'I represent an unordered collection of possibly duplicate elements.
  3454.     
  3455. I store these elements in a dictionary, tallying up occurrences of equal objects. Because I store an occurrence only once, my clients should beware that objects they store will not necessarily be retrieved such that == is true. If the client cares, a subclass of me should be created.'!
  3456.  
  3457.  
  3458. !Bag methodsFor: 'accessing'!
  3459. at: index
  3460.  
  3461.     self errorNotKeyed! !
  3462.  
  3463. !Bag methodsFor: 'accessing'!
  3464. at: index put: anObject
  3465.  
  3466.     self errorNotKeyed! !
  3467.  
  3468. !Bag methodsFor: 'accessing' stamp: 'di 9/11/97 16:14'!
  3469. cumulativeCounts
  3470.     "Answer with a collection of cumulative percents covered by elements so far."
  3471.     | s n |
  3472.     s _ self size // 100.0. n _ 0.
  3473.     ^ self sortedCounts asArray collect:
  3474.         [:a | n _ n + a key. (n // s roundTo: 0.1) -> a value]! !
  3475.  
  3476. !Bag methodsFor: 'accessing'!
  3477. size
  3478.  
  3479.     | tally |
  3480.     tally _ 0.
  3481.     contents do: [:each | tally _ tally + each].
  3482.     ^tally! !
  3483.  
  3484. !Bag methodsFor: 'accessing'!
  3485. sortedCounts
  3486.     "Answer with a collection of counts with elements, sorted by decreasing
  3487.     count."
  3488.  
  3489.     | counts |
  3490.     counts _ SortedCollection sortBlock: [:x :y | x >= y].
  3491.     contents associationsDo:
  3492.         [:assn |
  3493.         counts add: (Association key: assn value value: assn key)].
  3494.     ^counts! !
  3495.  
  3496. !Bag methodsFor: 'accessing'!
  3497. sortedElements
  3498.     "Answer with a collection of elements with counts, sorted by element."
  3499.  
  3500.     | elements |
  3501.     elements _ SortedCollection new.
  3502.     contents associationsDo: [:assn | elements add: assn].
  3503.     ^elements! !
  3504.  
  3505.  
  3506. !Bag methodsFor: 'testing'!
  3507. includes: anObject 
  3508.     "Refer to the comment in Collection|includes:."
  3509.  
  3510.     ^contents includesKey: anObject! !
  3511.  
  3512. !Bag methodsFor: 'testing'!
  3513. occurrencesOf: anObject 
  3514.     "Refer to the comment in Collection|occurrencesOf:."
  3515.  
  3516.     (self includes: anObject)
  3517.         ifTrue: [^contents at: anObject]
  3518.         ifFalse: [^0]! !
  3519.  
  3520.  
  3521. !Bag methodsFor: 'adding'!
  3522. add: newObject 
  3523.     "Refer to the comment in Collection|add:."
  3524.  
  3525.     ^self add: newObject withOccurrences: 1! !
  3526.  
  3527. !Bag methodsFor: 'adding'!
  3528. add: newObject withOccurrences: anInteger 
  3529.     "Add the element newObject to the receiver. Do so as though the element 
  3530.     were added anInteger number of times. Answer newObject."
  3531.  
  3532.     (self includes: newObject)
  3533.         ifTrue: [contents at: newObject put: anInteger + (contents at: newObject)]
  3534.         ifFalse: [contents at: newObject put: anInteger].
  3535.     ^newObject! !
  3536.  
  3537.  
  3538. !Bag methodsFor: 'removing'!
  3539. remove: oldObject ifAbsent: exceptionBlock 
  3540.     "Refer to the comment in Collection|remove:ifAbsent:."
  3541.  
  3542.     | count |
  3543.     (self includes: oldObject)
  3544.         ifTrue: [(count _ contents at: oldObject) = 1
  3545.                 ifTrue: [contents removeKey: oldObject]
  3546.                 ifFalse: [contents at: oldObject put: count - 1]]
  3547.         ifFalse: [^exceptionBlock value].
  3548.     ^oldObject! !
  3549.  
  3550.  
  3551. !Bag methodsFor: 'enumerating' stamp: 'SqR 11/4/97 19:58'!
  3552. asSet
  3553.     "Answer a set with the elements of the receiver"
  3554.  
  3555.      ^contents keys! !
  3556.  
  3557. !Bag methodsFor: 'enumerating'!
  3558. do: aBlock 
  3559.     "Refer to the comment in Collection|do:."
  3560.  
  3561.     contents associationsDo: [:assoc | assoc value timesRepeat: [aBlock value: assoc key]]! !
  3562.  
  3563.  
  3564. !Bag methodsFor: 'private'!
  3565. setDictionary
  3566.  
  3567.     contents _ Dictionary new! !
  3568.  
  3569. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3570.  
  3571. Bag class
  3572.     instanceVariableNames: ''!
  3573.  
  3574. !Bag class methodsFor: 'instance creation'!
  3575. new
  3576.  
  3577.     ^super new setDictionary! !
  3578.  
  3579. !Bag class methodsFor: 'instance creation'!
  3580. newFrom: aCollection 
  3581.     "Answer an instance of me containing the same elements as aCollection."
  3582.  
  3583.     | newCollection |
  3584.     newCollection _ self new.
  3585.     newCollection addAll: aCollection.
  3586.     ^newCollection
  3587.  
  3588. "    Bag newFrom: {1. 2. 3}
  3589.     {1. 2. 3} as: Bag
  3590. "! !
  3591. CurveMorph subclass: #BalloonMorph
  3592.     instanceVariableNames: 'target offsetFromTarget '
  3593.     classVariableNames: 'BalloonFont '
  3594.     poolDictionaries: ''
  3595.     category: 'Morphic-Widgets'!
  3596. !BalloonMorph commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3597. BalloonMorph comment:
  3598. 'A balloon with text used for the display of explanatory information.
  3599.  
  3600. Balloon help is integrated into Morphic as follows:
  3601. If a Morph has the property #balloonText, then it will respond to #showBalloon by adding a text balloon to the world, and to #deleteBalloon by removing the balloon.
  3602.  
  3603. Moreover, if mouseOverEnabled is true (see class msg), then the Hand will arrange to cause display of the balloon after the mouse has lingered over the morph for a while, and removal of the balloon when the mouse leaves the bounds of that morph.  In any case, the Hand will attempt to remove any such balloons before handling mouseDown events, or displaying other balloons.'!
  3604.  
  3605.  
  3606. !BalloonMorph methodsFor: 'all' stamp: 'di 9/17/97 19:26'!
  3607. setTarget: aMorph
  3608.     target _ aMorph.
  3609.     offsetFromTarget _ self position - target position! !
  3610.  
  3611. !BalloonMorph methodsFor: 'all' stamp: 'di 9/17/97 19:27'!
  3612. step
  3613.     self position: target position + offsetFromTarget! !
  3614.  
  3615. !BalloonMorph methodsFor: 'all' stamp: 'di 9/18/97 10:10'!
  3616. stepTime
  3617.     ^ 0  "every cycle"! !
  3618.  
  3619. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3620.  
  3621. BalloonMorph class
  3622.     instanceVariableNames: ''!
  3623.  
  3624. !BalloonMorph class methodsFor: 'all' stamp: 'di 10/20/97 20:10'!
  3625. chooseBalloonFont
  3626.     | sizes reply |
  3627.     sizes _ #(9 10 12 14).
  3628.     reply _ (SelectionMenu labelList: (sizes collect: [:s | s printString]) selections:  sizes) startUp.
  3629.     reply ifNotNil:
  3630.         [BalloonFont _ (TextStyle named: #ComicPlain) fontAt: (sizes indexOf: reply)]! !
  3631.  
  3632. !BalloonMorph class methodsFor: 'all' stamp: 'jm 5/20/1998 20:16'!
  3633. string: str for: morph corner: cornerName
  3634.     "Make up and return a balloon for morph.  Find the quadrant that
  3635. clips the text the least, using cornerName as a tie-breaker.  tk 9/12/97"
  3636.  
  3637.     | txt tm corners p1 p2 vertices c r maxArea aa verts mp dir mbc
  3638.  pref rectCorner morphPoint |
  3639.     BalloonFont
  3640.         ifNil: [txt _ str]
  3641.         ifNotNil: [txt _ Text string: str attribute: (TextFontReference toFont: BalloonFont)].
  3642.     tm _ (TextMorph new contents: txt) centered.
  3643.  
  3644.     "Construct vertices for a balloon below and to left of anchor"
  3645.     corners _ tm bounds corners atAll: #(1 4 3 2).
  3646.     p1 _ (corners at: 1) + ((0 - tm width//3)@0).
  3647.     p2 _ (corners at: 1) + ((0 - tm width//6)@(tm height//2)).
  3648.     vertices _ (Array with: p1 with: p2) , corners.
  3649.     r _ p1 rect: (corners at: 3).
  3650.     corners _ #(bottomRight bottomLeft topLeft topRight).
  3651.     pref _ corners indexOf: cornerName.
  3652.     c _ tm center.
  3653.     maxArea _ 0.
  3654.     (0 to: 3) do:
  3655.         [:i | "Try four rel locations of the balloon for greatest unclipped area"
  3656.         rectCorner _ corners atWrap: i+pref+2.
  3657.         morphPoint _ (#(bottomRight bottomLeft) includes: rectCorner)
  3658.                         ifTrue: [#topCenter] ifFalse: [#bottomCenter].
  3659.         aa _ ((r align: (r perform: rectCorner)
  3660.                 with: (mbc _ morph fullBoundsInWorld perform: morphPoint))
  3661.             intersect: (0@0 extent: morph world viewBox extent)) area.
  3662.         aa > maxArea ifTrue: [verts _ vertices.
  3663.                             maxArea _ aa.
  3664.                             mp _ mbc].
  3665.         dir _ (i+pref) odd ifTrue: [#horizontal] ifFalse: [#vertical].
  3666.         vertices _ vertices collect: [:p | p flipBy: dir centerAt: c]].
  3667.     ^ self new color: (Color r: 1.0 g: 1.0 b: 0.6);
  3668.             setBorderWidth: 1 borderColor: Color black;
  3669.             setVertices: verts;
  3670.             addMorph: tm;
  3671.             align: verts first with: mp;
  3672.             setTarget: morph! !
  3673. Object subclass: #Base64MimeConverter
  3674.     instanceVariableNames: 'dataStream mimeStream data '
  3675.     classVariableNames: 'FromCharTable ToCharTable '
  3676.     poolDictionaries: ''
  3677.     category: 'Collections-Streams'!
  3678. !Base64MimeConverter commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3679. This class encodes and decodes data in Base64 format.  This is MIME encoding.  We translate a whole stream at once, taking a Stream as input and giving one as output.  Returns a whole stream for the caller to use.
  3680.            0 A            17 R            34 i            51 z
  3681.            1 B            18 S            35 j            52 0
  3682.            2 C            19 T            36 k            53 1
  3683.            3 D            20 U            37 l            54 2
  3684.            4 E            21 V            38 m            55 3
  3685.            5 F            22 W            39 n            56 4
  3686.            6 G            23 X            40 o            57 5
  3687.            7 H            24 Y            41 p            58 6
  3688.            8 I            25 Z            42 q            59 7
  3689.            9 J            26 a            43 r            60 8
  3690.           10 K            27 b            44 s            61 9
  3691.           11 L            28 c            45 t            62 +
  3692.           12 M            29 d            46 u            63 /
  3693.           13 N            30 e            47 v
  3694.           14 O            31 f            48 w         (pad) =
  3695.           15 P            32 g            49 x
  3696.           16 Q            33 h            50 y
  3697. Outbound: bytes are broken into 6 bit chunks, and the 0-63 value is converted to a character.  3 data bytes go into 4 characters.
  3698. Inbound: Characters are translated in to 0-63 values and shifted into 8 bit bytes.
  3699.  
  3700. (See: N. Borenstein, Bellcore, N. Freed, Innosoft, Network Working Group, Request for Comments: RFC 1521, September 1993, MIME (Multipurpose Internet Mail Extensions) Part One: Mechanisms for Specifying and Describing the Format of Internet Message Bodies. Sec 6.2)
  3701.  
  3702. By Ted Kaehler, based on Tim Olson's Base64Filter.!
  3703.  
  3704.  
  3705. !Base64MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:55'!
  3706. dataStream
  3707.     ^dataStream! !
  3708.  
  3709. !Base64MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:51'!
  3710. dataStream: anObject
  3711.     dataStream _ anObject! !
  3712.  
  3713. !Base64MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:53'!
  3714. mimeStream
  3715.     ^mimeStream! !
  3716.  
  3717. !Base64MimeConverter methodsFor: 'accessing' stamp: 'tk 12/9/97 13:51'!
  3718. mimeStream: anObject
  3719.     mimeStream _ anObject! !
  3720.  
  3721.  
  3722. !Base64MimeConverter methodsFor: 'conversion' stamp: 'tk 12/9/97 13:34'!
  3723. mimeDecode
  3724.     "Convert a stream in base 64 with only a-z,A-Z,0-9,+,/ to a full byte stream of characters.  Reutrn a whole stream for the user to read."
  3725.  
  3726.     | nibA nibB nibC nibD |
  3727.     [mimeStream atEnd] whileFalse: [
  3728.         (nibA _ self nextValue) ifNil: [^ dataStream].
  3729.         (nibB _ self nextValue) ifNil: [^ dataStream].
  3730.         dataStream nextPut: ((nibA bitShift: 2) + (nibB bitShift: -4)) asCharacter.
  3731.         nibB _ nibB bitAnd: 16rF.
  3732.         (nibC _ self nextValue) ifNil: [^ dataStream].
  3733.         dataStream nextPut: ((nibB bitShift: 4) + (nibC bitShift: -2)) asCharacter.
  3734.         nibC _ nibC bitAnd: 16r3.
  3735.         (nibD _ self nextValue) ifNil: [^ dataStream].
  3736.         dataStream nextPut: ((nibC bitShift: 6) + nibD) asCharacter.
  3737.         ].
  3738.     ^ dataStream! !
  3739.  
  3740. !Base64MimeConverter methodsFor: 'conversion' stamp: 'tk 12/9/97 13:39'!
  3741. mimeDecodeToByteArray
  3742.     "Convert a stream in base 64 with only a-z,A-Z,0-9,+,/ to a full ByteArray of 0-255 values.  Reutrn a whole stream for the user to read."
  3743.  
  3744.     | nibA nibB nibC nibD |
  3745.     [mimeStream atEnd] whileFalse: [
  3746.         (nibA _ self nextValue) ifNil: [^ dataStream].
  3747.         (nibB _ self nextValue) ifNil: [^ dataStream].
  3748.         dataStream nextPut: ((nibA bitShift: 2) + (nibB bitShift: -4)).
  3749.         nibB _ nibB bitAnd: 16rF.
  3750.         (nibC _ self nextValue) ifNil: [^ dataStream].
  3751.         dataStream nextPut: ((nibB bitShift: 4) + (nibC bitShift: -2)).
  3752.         nibC _ nibC bitAnd: 16r3.
  3753.         (nibD _ self nextValue) ifNil: [^ dataStream].
  3754.         dataStream nextPut: ((nibC bitShift: 6) + nibD).
  3755.         ].
  3756.     ^ dataStream! !
  3757.  
  3758. !Base64MimeConverter methodsFor: 'conversion' stamp: 'tk 12/9/97 12:57'!
  3759. mimeEncode
  3760.     "Convert from data to 6 bit characters."
  3761.  
  3762.     | phase1 phase2 raw nib |
  3763.     phase1 _ phase2 _ false.
  3764.     [dataStream atEnd] whileFalse: [
  3765.         data _ raw _ dataStream next asInteger.
  3766.         nib _ (data bitAnd: 16rFC) bitShift: -2.
  3767.         mimeStream nextPut: (ToCharTable at: nib+1).
  3768.         (raw _ dataStream next) ifNil: [raw _ 0. phase1 _ true].
  3769.         data _ ((data bitAnd: 3) bitShift: 8) + raw asInteger.
  3770.         nib _ (data bitAnd: 16r3F0) bitShift: -4.
  3771.         mimeStream nextPut: (ToCharTable at: nib+1).
  3772.         (raw _ dataStream next) ifNil: [raw _ 0. phase2 _ true].
  3773.         data _ ((data bitAnd: 16rF) bitShift: 8) + (raw asInteger).
  3774.         nib _ (data bitAnd: 16rFC0) bitShift: -6.
  3775.         mimeStream nextPut: (ToCharTable at: nib+1).
  3776.         nib _ (data bitAnd: 16r3F).
  3777.         mimeStream nextPut: (ToCharTable at: nib+1)].
  3778.     phase1 ifTrue: [mimeStream skip: -2; nextPut: $=; nextPut: $=.
  3779.             ^ mimeStream].
  3780.     phase2 ifTrue: [mimeStream skip: -1; nextPut: $=.
  3781.             ^ mimeStream].
  3782.  
  3783. ! !
  3784.  
  3785. !Base64MimeConverter methodsFor: 'conversion' stamp: 'tk 12/9/97 13:21'!
  3786. nextValue
  3787.     "The next six bits of data char from the mimeStream, or nil.  Skip all other chars"
  3788.     | raw num |
  3789.     [raw _ mimeStream next.
  3790.     raw ifNil: [^ nil].    "end of stream"
  3791.     raw == $= ifTrue: [^ nil].
  3792.     num _ FromCharTable at: raw asciiValue + 1.
  3793.     num ifNotNil: [^ num].
  3794.     "else ignore space, return, tab, ..."
  3795.     true] whileTrue.! !
  3796.  
  3797. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  3798.  
  3799. Base64MimeConverter class
  3800.     instanceVariableNames: ''!
  3801.  
  3802. !Base64MimeConverter class methodsFor: 'as yet unclassified' stamp: 'tk 12/9/97 14:29'!
  3803. example
  3804.     "Base64MimeConverter example"
  3805.  
  3806. | ss bb | 
  3807. ss _ ReadWriteStream on: (String new: 10).
  3808. ss nextPutAll: 'Hi There!!'.
  3809. bb _ Base64MimeConverter mimeEncode: ss.
  3810.     "bb contents  'SGkgVGhlcmUh'"
  3811. ^ (Base64MimeConverter mimeDecodeToChars: bb) contents
  3812.  
  3813. ! !
  3814.  
  3815. !Base64MimeConverter class methodsFor: 'as yet unclassified' stamp: 'tk 12/9/97 13:53'!
  3816. initialize
  3817.  
  3818.     FromCharTable _ Array new: 256.    "nils"
  3819.     ToCharTable _ Array new: 64.
  3820.     ($A asciiValue to: $Z asciiValue) doWithIndex: [:val :ind | 
  3821.         FromCharTable at: val+1 put: ind-1.
  3822.         ToCharTable at: ind put: val asCharacter].
  3823.     ($a asciiValue to: $z asciiValue) doWithIndex: [:val :ind | 
  3824.         FromCharTable at: val+1 put: ind+25.
  3825.         ToCharTable at: ind+26 put: val asCharacter].
  3826.     ($0 asciiValue to: $9 asciiValue) doWithIndex: [:val :ind | 
  3827.         FromCharTable at: val+1 put: ind+25+26.
  3828.         ToCharTable at: ind+26+26 put: val asCharacter].
  3829.     FromCharTable at: $+ asciiValue + 1 put: 62.
  3830.     ToCharTable at: 63 put: $+.
  3831.     FromCharTable at: $/ asciiValue + 1 put: 63.
  3832.     ToCharTable at: 64 put: $/.
  3833.     ! !
  3834.  
  3835. !Base64MimeConverter class methodsFor: 'as yet unclassified' stamp: 'tk 12/12/97 11:41'!
  3836. mimeDecodeToBytes: aStream 
  3837.     "Return a RWBinaryOrTextStream of the original ByteArray.  aStream has only 65 innocuous character values.  aStream is not binary.  (See class comment). 4 bytes in aStream goes to 3 bytes in output."
  3838.  
  3839.     | me |
  3840.     aStream position: 0.
  3841.     me _ self new mimeStream: aStream.
  3842.     me dataStream: (RWBinaryOrTextStream on: (ByteArray new: aStream size * 3 // 4)).
  3843.     me mimeDecodeToByteArray.
  3844.     me dataStream position: 0.
  3845.     ^ me dataStream! !
  3846.  
  3847. !Base64MimeConverter class methodsFor: 'as yet unclassified' stamp: 'tk 12/9/97 13:01'!
  3848. mimeDecodeToChars: aStream 
  3849.     "Return a ReadWriteStream of the original String.  aStream has only 65 innocuous character values.  It is not binary.  (See class comment). 4 bytes in aStream goes to 3 bytes in output."
  3850.  
  3851.     | me |
  3852.     aStream position: 0.
  3853.     me _ self new mimeStream: aStream.
  3854.     me dataStream: (ReadWriteStream on: (String new: aStream size * 3 // 4)).
  3855.     me mimeDecode.
  3856.     me dataStream position: 0.
  3857.     ^ me dataStream! !
  3858.  
  3859. !Base64MimeConverter class methodsFor: 'as yet unclassified' stamp: 'tk 12/9/97 12:28'!
  3860. mimeEncode: aStream
  3861.     "Return a ReadWriteStream of characters.  The data of aStream is encoded as 65 innocuous characters.  (See class comment). 3 bytes in aStream goes to 4 bytes in output."
  3862.  
  3863.     | me |
  3864.     aStream position: 0.
  3865.     me _ self new dataStream: aStream.
  3866.     me mimeStream: (ReadWriteStream on: (String new: aStream size + 20 * 4 // 3)).
  3867.     me mimeEncode.
  3868.     me mimeStream position: 0.
  3869.     ^ me mimeStream! !
  3870. Object subclass: #Behavior
  3871.     instanceVariableNames: 'superclass methodDict format subclasses '
  3872.     classVariableNames: ''
  3873.     poolDictionaries: ''
  3874.     category: 'Kernel-Classes'!
  3875. !Behavior commentStamp: 'di 5/22/1998 16:32' prior: 0!
  3876. Behavior comment:
  3877. 'My instances describe the behavior of other objects. I provide the minimum state necessary for compiling methods, and creating and running instances. Most objects are created as instances of the more fully supported subclass, Class, but I am a good starting point for providing instance-specific behavior (as in Metaclass).'!
  3878.  
  3879.  
  3880. !Behavior methodsFor: 'initialize-release'!
  3881. obsolete
  3882.     "Invalidate and recycle local messages. Remove the receiver from its 
  3883.     superclass' subclass list."
  3884.  
  3885.     methodDict _ MethodDictionary new.
  3886.     superclass == nil ifFalse: [superclass removeSubclass: self]! !
  3887.  
  3888.  
  3889. !Behavior methodsFor: 'accessing'!
  3890. compilerClass
  3891.     "Answer a compiler class appropriate for source methods of this class."
  3892.  
  3893.     ^Compiler! !
  3894.  
  3895. !Behavior methodsFor: 'accessing' stamp: 'sw 3/10/97'!
  3896. confirmRemovalOf: aSelector
  3897.     "Determine if it is okay to remove the given selector.  Answer 1 if it should be removed, 2 if it should be removed followed by a senders browse, and 3 if it should not be removed. 
  3898.     9/18/96 sw: made the wording more delicate
  3899.     : bug fix -- auto select string needs to be first keyword only"
  3900.  
  3901.     | count aMenu answer caption allCalls |
  3902.     (count _ (allCalls _ Smalltalk allCallsOn: aSelector) size) > 0
  3903.         ifTrue:
  3904.             [aMenu _ PopUpMenu labels: 'Remove it
  3905. Remove, then browse senders
  3906. Don''t remove, but show me those senders
  3907. Forget it -- do nothing -- sorry I asked'.
  3908.  
  3909.             caption _ 'This message has ', count printString, ' sender'.
  3910.             count > 1 ifTrue:
  3911.                 [caption _ caption copyWith: $s].
  3912.             answer _ aMenu startUpWithCaption: caption.
  3913.             answer == 3 ifTrue:
  3914.                 [Smalltalk browseMessageList: allCalls
  3915.                     name: 'Senders of ', aSelector
  3916.                     autoSelect: aSelector keywords first].
  3917.             answer == 0 ifTrue: [answer _ 3].  "If user didn't answer, treat it as cancel"
  3918.             ^ answer min: 3]
  3919.         ifFalse:
  3920.             [^ 1]
  3921.     ! !
  3922.  
  3923. !Behavior methodsFor: 'accessing'!
  3924. decompilerClass
  3925.     "Answer a decompiler class appropriate for compiled methods of this class."
  3926.  
  3927.     ^Decompiler! !
  3928.  
  3929. !Behavior methodsFor: 'accessing'!
  3930. evaluatorClass
  3931.     "Answer an evaluator class appropriate for evaluating expressions in the 
  3932.     context of this class."
  3933.  
  3934.     ^Compiler! !
  3935.  
  3936. !Behavior methodsFor: 'accessing'!
  3937. format
  3938.     "Answer an Integer that encodes the kinds and numbers of variables of 
  3939.     instances of the receiver."
  3940.  
  3941.     ^format! !
  3942.  
  3943. !Behavior methodsFor: 'accessing'!
  3944. parserClass
  3945.     "Answer a parser class to use for parsing method headers."
  3946.  
  3947.     ^self compilerClass parserClass! !
  3948.  
  3949. !Behavior methodsFor: 'accessing'!
  3950. sourceCodeTemplate
  3951.     "Answer an expression to be edited and evaluated in order to define 
  3952.     methods in this class."
  3953.  
  3954.     ^'message selector and argument names
  3955.     "comment stating purpose of message"
  3956.  
  3957.     | temporary variable names |
  3958.     statements'! !
  3959.  
  3960. !Behavior methodsFor: 'accessing'!
  3961. subclassDefinerClass
  3962.     "Answer an evaluator class appropriate for evaluating definitions of new 
  3963.     subclasses of this class."
  3964.  
  3965.     ^Compiler! !
  3966.  
  3967.  
  3968. !Behavior methodsFor: 'testing'!
  3969. instSize
  3970.     "Answer the number of named instance variables
  3971.     (as opposed to indexed variables) of the receiver."
  3972.  
  3973.     self flag: #instSizeChange.  "Smalltalk browseAllCallsOn: #instSizeChange"
  3974. "
  3975.     NOTE: This code supports the backward-compatible extension to 8 bits of instSize.
  3976.     When we revise the image format, it should become...
  3977.     ^ ((format bitShift: -1) bitAnd: 16rFF) - 1
  3978.     Note also that every other method in this category will require
  3979.     2 bits more of right shift after the change.
  3980. "
  3981.     ^ ((format bitShift: -10) bitAnd: 16rC0) + ((format bitShift: -1) bitAnd: 16r3F) - 1! !
  3982.  
  3983. !Behavior methodsFor: 'testing'!
  3984. instSpec
  3985.     ^ (format bitShift: -7) bitAnd: 16rF! !
  3986.  
  3987. !Behavior methodsFor: 'testing'!
  3988. isBits
  3989.     "Answer whether the receiver contains just bits (not pointers)."
  3990.  
  3991.     ^ self instSpec >= 6! !
  3992.  
  3993. !Behavior methodsFor: 'testing'!
  3994. isBytes
  3995.     "Answer whether the receiver has 8-bit instance variables."
  3996.  
  3997.     ^ self instSpec >= 8! !
  3998.  
  3999. !Behavior methodsFor: 'testing'!
  4000. isFixed
  4001.     "Answer whether the receiver does not have a variable (indexable) part."
  4002.  
  4003.     ^self isVariable not! !
  4004.  
  4005. !Behavior methodsFor: 'testing'!
  4006. isPointers
  4007.     "Answer whether the receiver contains just pointers (not bits)."
  4008.  
  4009.     ^self isBits not! !
  4010.  
  4011. !Behavior methodsFor: 'testing'!
  4012. isVariable
  4013.     "Answer whether the receiver has indexable variables."
  4014.  
  4015.     ^ self instSpec >= 2! !
  4016.  
  4017. !Behavior methodsFor: 'testing'!
  4018. isWords
  4019.     "Answer whether the receiver has 16-bit instance variables."
  4020.  
  4021.     ^self isBytes not! !
  4022.  
  4023.  
  4024. !Behavior methodsFor: 'copying'!
  4025. copy
  4026.     "Answer a copy of the receiver without a list of subclasses."
  4027.  
  4028.     | myCopy savedSubclasses |
  4029.     savedSubclasses _ subclasses.
  4030.     subclasses _ nil.         
  4031.     myCopy _ self shallowCopy.
  4032.     subclasses _ savedSubclasses.
  4033.     ^myCopy methodDictionary: methodDict copy! !
  4034.  
  4035.  
  4036. !Behavior methodsFor: 'printing' stamp: 'sw 2/16/98 01:30'!
  4037. defaultNameStemForInstances
  4038.     "Answer a basis for names of default instances of the receiver"
  4039.     ^ self name! !
  4040.  
  4041. !Behavior methodsFor: 'printing'!
  4042. literalScannedAs: scannedLiteral notifying: requestor
  4043.     "Postprocesses a literal scanned by Scanner scanToken (esp. xLitQuote).
  4044.     If scannedLiteral is not an association, answer it.
  4045.     Else, if it is of the form:
  4046.         nil->#NameOfMetaclass
  4047.     answer nil->theMetaclass, if any has that name, else report an error.
  4048.     Else, if it is of the form:
  4049.         #NameOfGlobalVariable->anythiEng
  4050.     answer the global, class, or pool association with that nameE, if any, else
  4051.     add it to Undeclared a answer the new Association."
  4052.  
  4053.     | key value |
  4054.     (scannedLiteral isMemberOf: Association)
  4055.         ifFalse: [^ scannedLiteral].
  4056.     key _ scannedLiteral key.
  4057.     value _ scannedLiteral value.
  4058.     key isNil 
  4059.         ifTrue: "###<metaclass soleInstance name>"
  4060.             [self scopeHas: value ifTrue:
  4061.                 [:assoc |
  4062.                  (assoc value isKindOf: Behavior)
  4063.                     ifTrue: [^ nil->assoc value class]].
  4064.              requestor notify: 'No such metaclass'.
  4065.              ^false].
  4066.     (key isMemberOf: Symbol)
  4067.         ifTrue: "##<global var name>"
  4068.             [(self scopeHas: key ifTrue: [:assoc | ^assoc])
  4069.                 ifFalse:
  4070.                     [Undeclared at: key put: nil.
  4071.                      ^ Undeclared associationAt: key]].
  4072.     requestor notify: '## must be followed by a non-local variable name'.
  4073.     ^false
  4074.  
  4075. "    Form literalScannedAs: 14 notifying: nil 14
  4076.     Form literalScannedAs: #OneBitForm notiEfying: nil  OneBitForm
  4077.     Form literalScannedAs: ##OneBitForm notifying: nil  OneBitForm->a Form
  4078.     Form literalScannedAs: ##Form notifying: nil   Form->Form
  4079.     Form literalScannedAs: ###Form notifying: nil   nilE->Form class
  4080. "! !
  4081.  
  4082. !Behavior methodsFor: 'printing'!
  4083. printHierarchy
  4084.     "Answer a description containing the names and instance variable names 
  4085.     of all of the subclasses and superclasses of the receiver."
  4086.  
  4087.     | aStream index |
  4088.     index _ 0.
  4089.     aStream _ WriteStream on: (String new: 16).
  4090.     self allSuperclasses reverseDo: 
  4091.         [:aClass | 
  4092.         aStream crtab: index.
  4093.         index _ index + 1.
  4094.         aStream nextPutAll: aClass name.
  4095.         aStream space.
  4096.         aStream print: aClass instVarNames].
  4097.     aStream cr.
  4098.     self printSubclassesOn: aStream level: index.
  4099.     ^aStream contents! !
  4100.  
  4101. !Behavior methodsFor: 'printing'!
  4102. printOn: aStream 
  4103.     "Refer to the comment in Object|printOn:." 
  4104.  
  4105.     aStream nextPutAll: 'a descendent of '.
  4106.     superclass printOn: aStream! !
  4107.  
  4108. !Behavior methodsFor: 'printing'!
  4109. storeLiteral: aCodeLiteral on: aStream
  4110.     "Store aCodeLiteral on aStream, changing an Association to ##GlobalName
  4111.      or ###MetaclassSoleInstanceName format if appropriate"
  4112.     | key value |
  4113.     (aCodeLiteral isMemberOf: Association)
  4114.         ifFalse:
  4115.             [aCodeLiteral storeOn: aStream.
  4116.              ^self].
  4117.     key _ aCodeLiteral key.
  4118.     (key isNil and: [(value _ aCodeLiteral value) isMemberOf: Metaclass])
  4119.         ifTrue:
  4120.             [aStream nextPutAll: '###'; nextPutAll: value soleInstance name.
  4121.              ^self].
  4122.     ((key isMemberOf: Symbol) and: [self scopeHas: key ifTrue: [:ignore]])
  4123.         ifTrue:
  4124.             [aStream nextPutAll: '##'; nextPutAll: key.
  4125.              ^self].
  4126.     aCodeLiteral storeOn: aStream! !
  4127.  
  4128.  
  4129. !Behavior methodsFor: 'creating class hierarchy'!
  4130. addSubclass: aSubclass 
  4131.     "Make the argument, aSubclass, be one of the subclasses of the receiver. 
  4132.     Create an error notification if the argument's superclass is not the 
  4133.     receiver."
  4134.     
  4135.     aSubclass superclass ~~ self 
  4136.         ifTrue: [self error: aSubclass name , ' is not my subclass']
  4137.         ifFalse: [subclasses == nil
  4138.                     ifTrue:    [subclasses _ Set with: aSubclass]
  4139.                     ifFalse:    [subclasses add: aSubclass]]! !
  4140.  
  4141. !Behavior methodsFor: 'creating class hierarchy' stamp: 'tk 3/19/98 10:16'!
  4142. removeSubclass: aSubclass 
  4143.     "If the argument, aSubclass, is one of the receiver's subclasses, remove it."
  4144.  
  4145.     subclasses == nil ifFalse:
  4146.         [subclasses remove: aSubclass ifAbsent: [].
  4147.         subclasses isEmpty ifTrue: [subclasses _ nil]].
  4148.     Object flushCache.
  4149. ! !
  4150.  
  4151. !Behavior methodsFor: 'creating class hierarchy'!
  4152. superclass: aClass 
  4153.     "Change the receiver's superclass to be aClass."
  4154.  
  4155.     (aClass == nil or: [aClass isKindOf: Behavior])
  4156.         ifTrue: [superclass _ aClass]
  4157.         ifFalse: [self error: 'superclass must be a class-describing object']! !
  4158.  
  4159.  
  4160. !Behavior methodsFor: 'creating method dictionary' stamp: 'di 12/26/97 11:04'!
  4161. addSelector: selector withMethod: compiledMethod 
  4162.     "Add the message selector with the corresponding compiled method to the 
  4163.     receiver's method dictionary."
  4164.  
  4165.     methodDict at: selector put: compiledMethod.
  4166.     selector flushCache! !
  4167.  
  4168. !Behavior methodsFor: 'creating method dictionary'!
  4169. compile: code 
  4170.     "Compile the argument, code, as source code in the context of the 
  4171.     receiver. Create an error notification if the code can not be compiled. 
  4172.     The argument is either a string or an object that converts to a string or a 
  4173.     PositionableStream on an object that converts to a string."
  4174.  
  4175.     ^self compile: code notifying: nil! !
  4176.  
  4177. !Behavior methodsFor: 'creating method dictionary' stamp: 'tk 12/6/97 21:33'!
  4178. compile: code notifying: requestor 
  4179.     "Compile the argument, code, as source code in the context of the 
  4180.     receiver and insEtall the result in the receiver's method dictionary. The 
  4181.     second argument, requestor, is to be notified if an error occurs. The 
  4182.     argument code is either a string or an object that converts to a string or 
  4183.     a PositionableStream. This method also saves the source code."
  4184.     | method selector methodNode |
  4185.     method _ self
  4186.         compile: code "a Text"
  4187.         notifying: requestor
  4188.         trailer: #(0 0 0 0)
  4189.         ifFail: [^nil]
  4190.         elseSetSelectorAndNode: 
  4191.             [:sel :parseNode | selector _ sel.  methodNode _ parseNode].
  4192.     method putSource: code "a Text" fromParseNode: methodNode inFile: 2
  4193.             withPreamble: [:f | f cr; nextPut: $!!; nextChunkPut: 'Behavior method'; cr].
  4194.     ^selector! !
  4195.  
  4196. !Behavior methodsFor: 'creating method dictionary'!
  4197. compileAll
  4198.     ^ self compileAllFrom: self! !
  4199.  
  4200. !Behavior methodsFor: 'creating method dictionary'!
  4201. compileAllFrom: oldClass
  4202.     "Compile all the methods in the receiver's method dictionary.
  4203.     This validates sourceCode and variable references and forces
  4204.     all methods to use the current bytecode set"
  4205.  
  4206.     self selectorsDo: [:sel | self recompile: sel from: oldClass]! !
  4207.  
  4208. !Behavior methodsFor: 'creating method dictionary'!
  4209. compress
  4210.     "Compact the method dictionary of the receiver."
  4211.  
  4212.     methodDict rehash! !
  4213.  
  4214. !Behavior methodsFor: 'creating method dictionary'!
  4215. decompile: selector 
  4216.     "Find the compiled code associated with the argument, selector, as a 
  4217.     message selector in the receiver's method dictionary and decompile it. 
  4218.     Answer the resulting source code as a string. Create an error notification 
  4219.     if the selector is not in the receiver's method dictionary."
  4220.  
  4221.     ^self decompilerClass new decompile: selector in: self! !
  4222.  
  4223. !Behavior methodsFor: 'creating method dictionary'!
  4224. defaultSelectorForMethod: aMethod 
  4225.     "Given a method, invent and answer an appropriate message selector (a 
  4226.     Symbol), that is, one that will parse with the correct number of 
  4227.     arguments."
  4228.  
  4229.     | aStream |
  4230.     aStream _ WriteStream on: (String new: 16).
  4231.     aStream nextPutAll: 'DoIt'.
  4232.     1 to: aMethod numArgs do: [:i | aStream nextPutAll: 'with:'].
  4233.     ^aStream contents asSymbol! !
  4234.  
  4235. !Behavior methodsFor: 'creating method dictionary'!
  4236. methodDictionary: aDictionary 
  4237.     "Store the argument, aDictionary, as the method dictionary of the 
  4238.     receiver."
  4239.  
  4240.     methodDict _ aDictionary! !
  4241.  
  4242. !Behavior methodsFor: 'creating method dictionary'!
  4243. recompile: selector from: oldClass
  4244.     "Compile the method associated with selector in the receiver's method dictionary."
  4245.     | method trailer methodNode |
  4246.     method _ self compiledMethodAt: selector.
  4247.     trailer _ (method size - 3 to: method size) collect: [:i | method at: i].
  4248.     methodNode _ self compilerClass new
  4249.                 compile: (oldClass sourceCodeAt: selector)
  4250.                 in: self
  4251.                 notifying: nil
  4252.                 ifFail: [^ self].   "Assume OK after proceed from SyntaxError"
  4253.     selector == methodNode selector ifFalse: [self error: 'selector changed!!'].
  4254.     self addSelector: selector withMethod: (methodNode generate: trailer).
  4255. ! !
  4256.  
  4257. !Behavior methodsFor: 'creating method dictionary'!
  4258. recompileChanges
  4259.     "Compile all the methods that are in the changes file.
  4260.     This validates sourceCode and variable references and forces
  4261.     methods to use the current bytecode set"
  4262.  
  4263.     self selectorsDo:
  4264.         [:sel | (self compiledMethodAt: sel) fileIndex > 1 ifTrue:
  4265.             [self recompile: sel from: self]]! !
  4266.  
  4267. !Behavior methodsFor: 'creating method dictionary' stamp: 'di 12/26/97 11:08'!
  4268. removeSelector: selector 
  4269.     "Assuming that the argument, selector (a Symbol), is a message selector 
  4270.     in the receiver's method dictionary, remove it. If the selector is not in 
  4271.     the method dictionary, create an error notification."
  4272.  
  4273.     methodDict removeKey: selector.
  4274.     selector flushCache! !
  4275.  
  4276.  
  4277. !Behavior methodsFor: 'instance creation'!
  4278. basicNew
  4279.     "Primitive. Answer an instance of the receiver (which is a class) with no 
  4280.     indexable variables. Fail if the class is indexable. Essential. See Object 
  4281.     documentation whatIsAPrimitive."
  4282.  
  4283.     <primitive: 70>
  4284.     self isVariable ifTrue: [ ^ self basicNew: 0 ].
  4285.     "space must be low"
  4286.     Smalltalk signalLowSpace.
  4287.     ^ self basicNew  "retry if user proceeds"
  4288. ! !
  4289.  
  4290. !Behavior methodsFor: 'instance creation'!
  4291. basicNew: anInteger 
  4292.     "Primitive. Answer an instance of the receiver (which is a class) with the 
  4293.     number of indexable variables specified by the argument, anInteger. Fail 
  4294.     if the class is not indexable or if the argument is not a positive Integer. 
  4295.     Essential. See Object documentation whatIsAPrimitive."
  4296.  
  4297.     <primitive: 71>
  4298.     (anInteger isInteger and: [anInteger >= 0]) ifTrue: [
  4299.         "arg okay; space must be low"
  4300.         Smalltalk signalLowSpace.
  4301.         ^ self basicNew: anInteger  "retry if user proceeds"
  4302.     ].
  4303.     self primitiveFailed! !
  4304.  
  4305. !Behavior methodsFor: 'instance creation'!
  4306. new
  4307.     "Answer a new instance of the receiver (which is a class) with no indexable variables. Fail if the class is indexable."
  4308.     "Essential Primitive. See Object documentation whatIsAPrimitive."
  4309.  
  4310.     <primitive: 70>
  4311.     self isVariable ifTrue: [^ self basicNew: 0].
  4312.     "space must be low"
  4313.     Smalltalk signalLowSpace.
  4314.     ^ self basicNew  "retry if user proceeds"
  4315. ! !
  4316.  
  4317. !Behavior methodsFor: 'instance creation'!
  4318. new: anInteger 
  4319.     "Primitive. Answer an instance of the receiver (which is a class) with the 
  4320.     number of indexable variables specified by the argument, anInteger. Fail 
  4321.     if the class is not indexable or if the argument is not a positive Integer. 
  4322.     Essential. See Object documentation whatIsAPrimitive."
  4323.  
  4324.     <primitive: 71>
  4325.     (anInteger isInteger and: [anInteger >= 0]) ifTrue: [
  4326.         "arg okay; space must be low"
  4327.         Smalltalk signalLowSpace.
  4328.         ^ self basicNew: anInteger  "retry if user proceeds"
  4329.     ].
  4330.     self primitiveFailed! !
  4331.  
  4332.  
  4333. !Behavior methodsFor: 'accessing class hierarchy'!
  4334. allSubclasses
  4335.     "Answer a Set of the receiver's and the receiver's descendent's subclasses."
  4336.  
  4337.     | aSet |
  4338.     aSet _ Set new.
  4339.     aSet addAll: self subclasses.
  4340.     self subclasses do: [:eachSubclass | aSet addAll: eachSubclass allSubclasses].
  4341.     ^aSet! !
  4342.  
  4343. !Behavior methodsFor: 'accessing class hierarchy'!
  4344. allSubclassesWithLevelDo: classAndLevelBlock startingLevel: level 
  4345.     "Walk the tree of subclasses, giving the class and its level"
  4346.     | subclassNames subclass |
  4347.     classAndLevelBlock value: self value: level.
  4348.     self == Class ifTrue:  [^ self].  "Don't visit all the metaclasses"
  4349.     "Visit subclasses in alphabetical order"
  4350.     subclassNames _ SortedCollection new.
  4351.     self subclassesDo: [:subC | subclassNames add: subC name].
  4352.     subclassNames do:
  4353.         [:name | (Smalltalk at: name)
  4354.             allSubclassesWithLevelDo: classAndLevelBlock
  4355.             startingLevel: level+1]! !
  4356.  
  4357. !Behavior methodsFor: 'accessing class hierarchy'!
  4358. allSuperclasses
  4359.     "Answer an OrderedCollection of the receiver's and the receiver's 
  4360.     ancestor's superclasses. The first element is the receiver's immediate 
  4361.     superclass, followed by its superclass; the last element is Object."
  4362.  
  4363.     | temp |
  4364.     superclass == nil
  4365.         ifTrue: [^OrderedCollection new]
  4366.         ifFalse: [temp _ superclass allSuperclasses.
  4367.                 temp addFirst: superclass.
  4368.                 ^temp]! !
  4369.  
  4370. !Behavior methodsFor: 'accessing class hierarchy'!
  4371. subclasses
  4372.     "Answer a Set containing the receiver's subclasses."
  4373.  
  4374.     subclasses == nil
  4375.         ifTrue: [^Set new]
  4376.         ifFalse: [^subclasses copy]! !
  4377.  
  4378. !Behavior methodsFor: 'accessing class hierarchy'!
  4379. superclass
  4380.     "Answer the receiver's superclass, a Class."
  4381.  
  4382.     ^superclass! !
  4383.  
  4384. !Behavior methodsFor: 'accessing class hierarchy'!
  4385. withAllSubclasses
  4386.     "Answer a Set of the receiver, the receiver's descendent's, and the 
  4387.     receiver's descendent's subclasses."
  4388.  
  4389.     | aSet |
  4390.     aSet _ Set with: self.
  4391.     aSet addAll: self subclasses.
  4392.     self subclasses do: [:eachSubclass | aSet addAll: eachSubclass allSubclasses].
  4393.     ^aSet! !
  4394.  
  4395. !Behavior methodsFor: 'accessing class hierarchy'!
  4396. withAllSuperclasses
  4397.     "Answer an OrderedCollection of the receiver and the receiver's 
  4398.     superclasses. The first element is the receiver, 
  4399.     followed by its superclass; the last element is Object."
  4400.  
  4401.     | temp |
  4402.     temp _ self allSuperclasses.
  4403.     temp addFirst: self.
  4404.     ^ temp! !
  4405.  
  4406.  
  4407. !Behavior methodsFor: 'accessing method dictionary'!
  4408. allSelectors
  4409.     "Answer a Set of all the message selectors that instances of the receiver 
  4410.     can understand."
  4411.  
  4412.     | temp |
  4413.     superclass == nil
  4414.         ifTrue: [^self selectors]
  4415.         ifFalse: [temp _ superclass allSelectors.
  4416.                 temp addAll: self selectors.
  4417.                 ^temp]
  4418.  
  4419.     "Point allSelectors"! !
  4420.  
  4421. !Behavior methodsFor: 'accessing method dictionary'!
  4422. changeRecordsAt: selector
  4423.     "Return a list of ChangeRecords for all versions of the method at selector.
  4424.     Source code can be retrieved by sending string to any one"
  4425.     "(Pen changeRecordsAt: #go:) collect: [:cRec | cRec string]"
  4426.     ^ (ChangeList new
  4427.             scanVersionsOf: (self compiledMethodAt: selector)
  4428.             class: self meta: self isMeta
  4429.             category: (self whichCategoryIncludesSelector: selector)
  4430.             selector: selector)
  4431.         changeList! !
  4432.  
  4433. !Behavior methodsFor: 'accessing method dictionary'!
  4434. compiledMethodAt: selector 
  4435.     "Answer the compiled method associated with the argument, selector (a 
  4436.     Symbol), a message selector in the receiver's method dictionary. If the 
  4437.     selector is not in the dictionary, create an error notification."
  4438.  
  4439.     ^methodDict at: selector! !
  4440.  
  4441. !Behavior methodsFor: 'accessing method dictionary' stamp: 'sw 1/15/98 19:34'!
  4442. compiledMethodAt: selector ifAbsent: aBlock
  4443.     "Answer the compiled method associated with the argument, selector (a Symbol), a message selector in the receiver's method dictionary. If the selector is not in the dictionary, return the value of aBlock"
  4444.  
  4445.     ^ methodDict at: selector ifAbsent: [aBlock value]! !
  4446.  
  4447. !Behavior methodsFor: 'accessing method dictionary' stamp: 'tk 1/7/98 10:31'!
  4448. compressedSourceCodeAt: selector
  4449.     "(Paragraph compressedSourceCodeAt: #displayLines:affectedRectangle:) size 721 1921
  4450.     Paragraph selectors inject: 0 into: [:tot :sel | tot + (Paragraph compressedSourceCodeAt: sel) size] 13606 31450"
  4451.     | rawText parse |
  4452.     rawText _ (self sourceCodeAt: selector) asString.
  4453.     parse _ self compilerClass new parse: rawText in: self notifying: nil.
  4454.     ^ rawText compressWithTable:
  4455.         ((selector keywords ,
  4456.         parse tempNames ,
  4457.         self instVarNames ,
  4458.         #(self super ifTrue: ifFalse:) ,
  4459.         ((0 to: 7) collect:
  4460.             [:i | String streamContents:
  4461.                 [:s | s cr. i timesRepeat: [s tab]]]) ,
  4462.         (self compiledMethodAt: selector) literalStrings)
  4463.             asSortedCollection: [:a :b | a size > b size])! !
  4464.  
  4465. !Behavior methodsFor: 'accessing method dictionary'!
  4466. firstCommentAt:  selector
  4467.     "Answer a string representing the first comment in the method associated with selector.  Return an empty string if the relevant source file is not available, or if the method's source code does not contain a comment.  Not smart enough to bypass quotes in string constants, but ""clever"" enough to map doubled quotes into a single quote.  5/1/96 sw"
  4468.     "Behavior firstCommentAt: #firstCommentAt:"
  4469.  
  4470.     | sourceString commentStart  pos nextQuotePos |
  4471.  
  4472.     sourceString _ self sourceCodeAt: selector.
  4473.     sourceString size == 0 ifTrue: [^ ''].
  4474.     commentStart _ sourceString findString: '"' startingAt: 1.
  4475.     commentStart == 0 ifTrue: [^ ''].
  4476.     pos _ commentStart + 1.
  4477.     [(nextQuotePos _ sourceString findString: '"' startingAt: pos) == (sourceString findString: '""' startingAt: pos)]
  4478.         whileTrue:
  4479.             [pos _ nextQuotePos + 2].
  4480.             
  4481.     ^ (sourceString copyFrom: commentStart + 1 to: nextQuotePos - 1) copyReplaceAll: '""' with: '"'! !
  4482.  
  4483. !Behavior methodsFor: 'accessing method dictionary'!
  4484. selectorAtMethod: method setClass: classResultBlock 
  4485.     "Answer both the message selector associated with the compiled method 
  4486.     and the class in which that selector is defined."
  4487.  
  4488.     | sel |
  4489.     sel _ methodDict keyAtValue: method
  4490.                 ifAbsent: 
  4491.                     [superclass == nil
  4492.                         ifTrue: 
  4493.                             [classResultBlock value: self.
  4494.                             ^self defaultSelectorForMethod: method].
  4495.                     sel _ superclass selectorAtMethod: method setClass: classResultBlock.
  4496.                     "Set class to be self, rather than that returned from 
  4497.                     superclass. "
  4498.                     sel == (self defaultSelectorForMethod: method) ifTrue: [classResultBlock value: self].
  4499.                     ^sel].
  4500.     classResultBlock value: self.
  4501.     ^sel! !
  4502.  
  4503. !Behavior methodsFor: 'accessing method dictionary'!
  4504. selectors
  4505.     "Answer a Set of all the message selectors specified in the receiver's 
  4506.     method dictionary."
  4507.  
  4508.     ^methodDict keys  
  4509.  
  4510.     "Point selectors."! !
  4511.  
  4512. !Behavior methodsFor: 'accessing method dictionary'!
  4513. selectorsDo: selectorBlock
  4514.     "Evaluate selectorBlock for all the message selectors in my method dictionary."
  4515.  
  4516.     ^methodDict keysDo: selectorBlock! !
  4517.  
  4518. !Behavior methodsFor: 'accessing method dictionary' stamp: 'di 1/13/98 17:34'!
  4519. sourceCodeAt: selector
  4520.  
  4521.     ^ (methodDict at: selector) getSourceFor: selector in: self! !
  4522.  
  4523. !Behavior methodsFor: 'accessing method dictionary' stamp: 'sw 11/3/97 00:09'!
  4524. sourceCodeAt: selector ifAbsent: aBlock
  4525.  
  4526.     ^ (methodDict at: selector ifAbsent: [^ aBlock value]) getSourceFor: selector in: self! !
  4527.  
  4528. !Behavior methodsFor: 'accessing method dictionary'!
  4529. sourceMethodAt: selector 
  4530.     "Answer the paragraph corresponding to the source code for the 
  4531.     argument."
  4532.  
  4533.     ^(self sourceCodeAt: selector) asText makeSelectorBoldIn: self! !
  4534.  
  4535. !Behavior methodsFor: 'accessing method dictionary' stamp: 'sw 11/3/97 00:10'!
  4536. sourceMethodAt: selector ifAbsent: aBlock
  4537.     "Answer the paragraph corresponding to the source code for the 
  4538.     argument."
  4539.  
  4540.     ^ (self sourceCodeAt: selector ifAbsent: [^ aBlock value]) asText makeSelectorBoldIn: self! !
  4541.  
  4542.  
  4543. !Behavior methodsFor: 'accessing instances and variables'!
  4544. allClassVarNames
  4545.     "Answer a Set of the names of the receiver's and the receiver's ancestor's 
  4546.     class variables."
  4547.  
  4548.     ^superclass allClassVarNames! !
  4549.  
  4550. !Behavior methodsFor: 'accessing instances and variables' stamp: 'jm 5/20/1998 15:53'!
  4551. allInstances 
  4552.     "Answer a collection of all current instances of the receiver."
  4553.  
  4554.     | all |
  4555.     all _ OrderedCollection new.
  4556.     self allInstancesDo: [:x | x == all ifFalse: [all add: x]].
  4557.     ^ all asArray
  4558. ! !
  4559.  
  4560. !Behavior methodsFor: 'accessing instances and variables'!
  4561. allInstVarNames
  4562.     "Answer an Array of the names of the receiver's instance variables. The 
  4563.     Array ordering is the order in which the variables are stored and 
  4564.     accessed by the interpreter."
  4565.  
  4566.     | vars |
  4567.     superclass == nil
  4568.         ifTrue: [vars _ self instVarNames copy]    "Guarantee a copy is answered."
  4569.         ifFalse: [vars _ superclass allInstVarNames , self instVarNames].
  4570.     ^vars! !
  4571.  
  4572. !Behavior methodsFor: 'accessing instances and variables'!
  4573. allSharedPools
  4574.     "Answer a Set of the names of the pools (Dictionaries) that the receiver 
  4575.     and the receiver's ancestors share."
  4576.  
  4577.     ^superclass allSharedPools! !
  4578.  
  4579. !Behavior methodsFor: 'accessing instances and variables' stamp: 'di 6/20/97 10:51'!
  4580. allSubInstances 
  4581.     "Answer a list of all current instances of the receiver and all of its subclasses."
  4582.     | aCollection |
  4583.     aCollection _ OrderedCollection new.
  4584.     self allSubInstancesDo:
  4585.         [:x | x == aCollection ifFalse: [aCollection add: x]].
  4586.     ^ aCollection! !
  4587.  
  4588. !Behavior methodsFor: 'accessing instances and variables'!
  4589. classVarNames
  4590.     "Answer a Set of the receiver's class variable names."
  4591.  
  4592.     ^Set new! !
  4593.  
  4594. !Behavior methodsFor: 'accessing instances and variables'!
  4595. inspectAllInstances 
  4596.     "Inpsect all instances of the receiver.  1/26/96 sw"
  4597.  
  4598.     | all allSize prefix |
  4599.     all _ self allInstances.
  4600.     (allSize _ all size) == 0 ifTrue: [^ self notify: 'There are no 
  4601. instances of ', self name].
  4602.     prefix _ allSize == 1
  4603.         ifTrue:     ['The lone instance']
  4604.         ifFalse:    ['The ', allSize printString, ' instances'].
  4605.     
  4606.     all asArray inspectWithLabel: (prefix, ' of ', self name)! !
  4607.  
  4608. !Behavior methodsFor: 'accessing instances and variables'!
  4609. inspectSubInstances 
  4610.     "Inspect all instances of the receiver and all its subclasses.  CAUTION - don't do this for something as generic as Object!!  1/26/96 sw"
  4611.  
  4612.     | all allSize prefix |
  4613.     all _ self allSubInstances.
  4614.     (allSize _ all size) == 0 ifTrue: [^ self notify: 'There are no 
  4615. instances of ', self name, '
  4616. or any of its subclasses'].
  4617.     prefix _ allSize == 1
  4618.         ifTrue:     ['The lone instance']
  4619.         ifFalse:    ['The ', allSize printString, ' instances'].
  4620.     
  4621.     all asArray inspectWithLabel: (prefix, ' of ', self name, ' & its subclasses')! !
  4622.  
  4623. !Behavior methodsFor: 'accessing instances and variables'!
  4624. instanceCount
  4625.     "Answer the number of instances of the receiver that are currently in 
  4626.     use."
  4627.  
  4628.     | count |
  4629.     count _ 0.
  4630.     self allInstancesDo: [:x | count _ count + 1].
  4631.     ^count! !
  4632.  
  4633. !Behavior methodsFor: 'accessing instances and variables'!
  4634. instVarNames
  4635.     "Answer an Array of the instance variable names. Behaviors must make 
  4636.     up fake local instance variable names because Behaviors have instance 
  4637.     variables for the purpose of compiling methods, but these are not named 
  4638.     instance variables."
  4639.  
  4640.     | mySize superSize |
  4641.     mySize _ self instSize.
  4642.     superSize _ 
  4643.         superclass == nil
  4644.             ifTrue: [0]
  4645.             ifFalse: [superclass instSize].
  4646.     mySize = superSize ifTrue: [^#()].    
  4647.     ^(superSize + 1 to: mySize) collect: [:i | 'inst' , i printString]! !
  4648.  
  4649. !Behavior methodsFor: 'accessing instances and variables'!
  4650. sharedPools
  4651.     "Answer a Set of the names of the pools (Dictionaries) that the receiver 
  4652.     shares.
  4653.     9/12/96 tk  sharedPools have an order now"
  4654.  
  4655.     ^ OrderedCollection new! !
  4656.  
  4657. !Behavior methodsFor: 'accessing instances and variables'!
  4658. someInstance
  4659.     "Primitive. Answer the first instance in the enumeration of all instances 
  4660.     of the receiver. Fails if there are none. Essential. See Object 
  4661.     documentation whatIsAPrimitive."
  4662.  
  4663.     <primitive: 77>
  4664.     ^nil! !
  4665.  
  4666. !Behavior methodsFor: 'accessing instances and variables'!
  4667. subclassInstVarNames
  4668.     "Answer a Set of the names of the receiver's subclasses' instance 
  4669.     variables."
  4670.     | vars |
  4671.     vars _ Set new.
  4672.     self allSubclasses do: [:aSubclass | vars addAll: aSubclass instVarNames].
  4673.     ^vars! !
  4674.  
  4675.  
  4676. !Behavior methodsFor: 'testing class hierarchy'!
  4677. inheritsFrom: aClass 
  4678.     "Answer whether the argument, aClass, is on the receiver's superclass 
  4679.     chain."
  4680.  
  4681.     | aSuperclass |
  4682.     aSuperclass _ superclass.
  4683.     [aSuperclass == nil]
  4684.         whileFalse: 
  4685.             [aSuperclass == aClass ifTrue: [^true].
  4686.             aSuperclass _ aSuperclass superclass].
  4687.     ^false! !
  4688.  
  4689. !Behavior methodsFor: 'testing class hierarchy'!
  4690. kindOfSubclass 
  4691.     "Answer a String that is the keyword that describes the receiver's kind of 
  4692.     subclass, either a regular subclass, a variableSubclass, a 
  4693.     variableByteSubclass, or a variableWordSubclass."
  4694.  
  4695.     self isVariable
  4696.         ifTrue: [self isBits
  4697.                     ifTrue: [self isBytes
  4698.                                 ifTrue: [^' variableByteSubclass: ']
  4699.                                 ifFalse: [^' variableWordSubclass: ']]
  4700.                     ifFalse: [^' variableSubclass: ']]
  4701.         ifFalse: [^' subclass: ']! !
  4702.  
  4703.  
  4704. !Behavior methodsFor: 'testing method dictionary'!
  4705. allUnsentMessages
  4706.     "Answer an array of all the messages defined by the receiver that are not sent anywhere in the system.  5/8/96 sw"
  4707.  
  4708.     ^ Smalltalk allUnSentMessagesIn: self selectors! !
  4709.  
  4710. !Behavior methodsFor: 'testing method dictionary'!
  4711. canUnderstand: selector 
  4712.     "Answer whether the receiver can respond to the message whose selector 
  4713.     is the argument. The selector can be in the method dictionary of the 
  4714.     receiver's class or any of its superclasses."
  4715.  
  4716.     (self includesSelector: selector) ifTrue: [^true].
  4717.     superclass == nil ifTrue: [^false].
  4718.     ^superclass canUnderstand: selector! !
  4719.  
  4720. !Behavior methodsFor: 'testing method dictionary' stamp: 'tk 9/13/97 09:53'!
  4721. classThatUnderstands: selector
  4722.     "Answer the class that can respond to the message whose selector
  4723.     is the argument. The selector can be in the method dictionary of the
  4724.     receiver's class or any of its superclasses."
  4725.  
  4726.     (self includesSelector: selector) ifTrue: [^ self].
  4727.     superclass == nil ifTrue: [^ nil].
  4728.     ^ superclass classThatUnderstands: selector! !
  4729.  
  4730. !Behavior methodsFor: 'testing method dictionary'!
  4731. hasMethods
  4732.     "Answer whether the receiver has any methods in its method dictionary."
  4733.  
  4734.     ^methodDict size > 0! !
  4735.  
  4736. !Behavior methodsFor: 'testing method dictionary'!
  4737. includesSelector: aSymbol 
  4738.     "Answer whether the message whose selector is the argument is in the 
  4739.     method dictionary of the receiver's class."
  4740.  
  4741.     ^methodDict includesKey: aSymbol! !
  4742.  
  4743. !Behavior methodsFor: 'testing method dictionary'!
  4744. scopeHas: name ifTrue: assocBlock 
  4745.     "If the argument name is a variable known to the receiver, then evaluate 
  4746.     the second argument, assocBlock."
  4747.  
  4748.     ^superclass scopeHas: name ifTrue: assocBlock! !
  4749.  
  4750. !Behavior methodsFor: 'testing method dictionary' stamp: 'di 9/5/97 16:16'!
  4751. thoroughWhichSelectorsReferTo: literal special: specialFlag byte: specialByte
  4752.     "Answer a set of selectors whose methods access the argument as a literal.  Dives into the compact literal notation, making it slow but thorough"
  4753.     | who method |
  4754.     who _ Set new.
  4755.     methodDict associationsDo:
  4756.         [:assn |
  4757.         method _ assn value.
  4758.         ((method hasLiteralSuchThat: [:lit | lit == literal]) or:
  4759.                 [specialFlag and: [method scanFor: specialByte]])
  4760.             ifTrue:
  4761.             [((literal isMemberOf: Association) not
  4762.                 or: [method sendsToSuper not
  4763.                     or: [method literals allButLast includes: literal]])
  4764.                 ifTrue: [who add: assn key]]].
  4765.     ^ who! !
  4766.  
  4767. !Behavior methodsFor: 'testing method dictionary'!
  4768. whichClassIncludesSelector: aSymbol 
  4769.     "Answer the class on the receiver's superclass chain where the argument, 
  4770.     aSymbol (a message selector), will be found. Answer nil if none found."
  4771.  
  4772.     (methodDict includesKey: aSymbol) ifTrue: [^self].
  4773.     superclass == nil ifTrue: [^nil].
  4774.     ^superclass whichClassIncludesSelector: aSymbol
  4775.  
  4776.     "Rectangle whichClassIncludesSelector: #inspect."! !
  4777.  
  4778. !Behavior methodsFor: 'testing method dictionary'!
  4779. whichSelectorsAccess: instVarName 
  4780.     "Answer a Set of selectors whose methods access the argument, 
  4781.     instVarName, as a named instance variable."
  4782.  
  4783.     | instVarIndex |
  4784.     instVarIndex _ self allInstVarNames indexOf: instVarName ifAbsent: [^Set new].
  4785.     ^methodDict keys select: 
  4786.         [:sel | 
  4787.         ((methodDict at: sel)
  4788.             readsField: instVarIndex)
  4789.             or: [(methodDict at: sel) writesField: instVarIndex]]
  4790.  
  4791.     "Point whichSelectorsAccess: 'x'."! !
  4792.  
  4793. !Behavior methodsFor: 'testing method dictionary'!
  4794. whichSelectorsReferTo: literal 
  4795.     "Answer a Set of selectors whose methods access the argument as a literal."
  4796.  
  4797.     | special |
  4798.     special _ Smalltalk hasSpecialSelector: literal ifTrueSetByte: [:byte ].
  4799.     ^self whichSelectorsReferTo: literal special: special byte: byte
  4800.  
  4801.     "Rectangle whichSelectorsReferTo: #+."! !
  4802.  
  4803. !Behavior methodsFor: 'testing method dictionary' stamp: 'di 10/17/97 22:39'!
  4804. whichSelectorsReferTo: literal special: specialFlag byte: specialByte
  4805.     "Answer a set of selectors whose methods access the argument as a literal."
  4806.     | who method |
  4807.     who _ Set new.
  4808.     methodDict associationsDo:
  4809.         [:assn |
  4810.         method _ assn value.
  4811.         ((method hasLiteral: literal) or:
  4812.                 [specialFlag and: [method scanFor: specialByte]])
  4813.             ifTrue:
  4814.             [((literal isMemberOf: Association) not
  4815.                 or: [method sendsToSuper not
  4816.                     or: [method literals allButLast includes: literal]])
  4817.                 ifTrue: [who add: assn key]]].
  4818.     ^who! !
  4819.  
  4820. !Behavior methodsFor: 'testing method dictionary'!
  4821. whichSelectorsStoreInto: instVarName 
  4822.     "Answer a Set of selectors whose methods access the argument, 
  4823.     instVarName, as a named instance variable."
  4824.     | instVarIndex |
  4825.     instVarIndex _ self allInstVarNames indexOf: instVarName ifAbsent: [^Set new].
  4826.     ^ methodDict keys select: 
  4827.         [:sel | (methodDict at: sel) writesField: instVarIndex]
  4828.  
  4829.     "Point whichSelectorsStoreInto: 'x'."! !
  4830.  
  4831.  
  4832. !Behavior methodsFor: 'enumerating'!
  4833. allInstancesDo: aBlock 
  4834.     "Evaluate the argument, aBlock, for each of the current instances of the 
  4835.     receiver."
  4836.     | inst next |
  4837.     self ==  UndefinedObject ifTrue: [^ aBlock value: nil].
  4838.     inst _ self someInstance.
  4839.     [inst == nil]
  4840.         whileFalse:
  4841.         [aBlock value: inst.
  4842.         inst _ inst nextInstance]! !
  4843.  
  4844. !Behavior methodsFor: 'enumerating'!
  4845. allSubclassesDo: aBlock 
  4846.     "Evaluate the argument, aBlock, for each of the receiver's subclasses."
  4847.  
  4848.     self subclassesDo: 
  4849.         [:cl | 
  4850.         aBlock value: cl.
  4851.         cl allSubclassesDo: aBlock]! !
  4852.  
  4853. !Behavior methodsFor: 'enumerating' stamp: 'di 6/20/97 10:50'!
  4854. allSubInstancesDo: aBlock 
  4855.     "Evaluate the argument, aBlock, for each of the current instances of the 
  4856.     receiver and all its subclasses."
  4857.  
  4858.     self allInstancesDo: aBlock.
  4859.     self allSubclassesDo: [:sub | sub allInstancesDo: aBlock]! !
  4860.  
  4861. !Behavior methodsFor: 'enumerating'!
  4862. allSuperclassesDo: aBlock 
  4863.     "Evaluate the argument, aBlock, for each of the receiver's superclasses."
  4864.  
  4865.     superclass == nil
  4866.         ifFalse: [aBlock value: superclass.
  4867.                 superclass allSuperclassesDo: aBlock]! !
  4868.  
  4869. !Behavior methodsFor: 'enumerating'!
  4870. selectSubclasses: aBlock 
  4871.     "Evaluate the argument, aBlock, with each of the receiver's (next level) 
  4872.     subclasses as its argument. Collect into a Set only those subclasses for 
  4873.     which aBlock evaluates to true. In addition, evaluate aBlock for the 
  4874.     subclasses of each of these successful subclasses and collect into the set 
  4875.     those for which aBlock evaluates true. Answer the resulting set."
  4876.  
  4877.     | aSet |
  4878.     aSet _ Set new.
  4879.     self allSubclasses do: 
  4880.         [:aSubclass | 
  4881.         (aBlock value: aSubclass) ifTrue: [aSet add: aSubclass]].
  4882.     ^aSet! !
  4883.  
  4884. !Behavior methodsFor: 'enumerating'!
  4885. selectSuperclasses: aBlock 
  4886.     "Evaluate the argument, aBlock, with the receiver's superclasses as the 
  4887.     argument. Collect into an OrderedCollection only those superclasses for 
  4888.     which aBlock evaluates to true. In addition, evaluate aBlock for the 
  4889.     superclasses of each of these successful superclasses and collect into the 
  4890.     OrderedCollection ones for which aBlock evaluates to true. Answer the 
  4891.     resulting OrderedCollection."
  4892.  
  4893.     | aSet |
  4894.     aSet _ Set new.
  4895.     self allSuperclasses do: 
  4896.         [:aSuperclass | 
  4897.         (aBlock value: aSuperclass) ifTrue: [aSet add: aSuperclass]].
  4898.     ^aSet! !
  4899.  
  4900. !Behavior methodsFor: 'enumerating'!
  4901. subclassesDo: aBlock 
  4902.     "Evaluate the argument, aBlock, for each of the receiver's immediate subclasses."
  4903.     subclasses == nil ifFalse:
  4904.         [subclasses do: [:cl | aBlock value: cl]]! !
  4905.  
  4906. !Behavior methodsFor: 'enumerating'!
  4907. withAllSubclassesDo: aBlock 
  4908.     "Evaluate the argument, aBlock, for the receiver and each of its 
  4909.     subclasses."
  4910.  
  4911.     aBlock value: self.
  4912.     self allSubclassesDo: aBlock! !
  4913.  
  4914.  
  4915. !Behavior methodsFor: 'user interface' stamp: 'sw 8/12/97 20:18'!
  4916. allCallsOn: aSymbol
  4917.     "Answer a SortedCollection of all the methods that call on aSymbol."
  4918.  
  4919.     | aSortedCollection special |
  4920.     aSortedCollection _ SortedCollection new.
  4921.     special _ Smalltalk hasSpecialSelector: aSymbol ifTrueSetByte: [:byte ].
  4922.     self withAllSubclassesDo:
  4923.         [:class | (class whichSelectorsReferTo: aSymbol special: special byte: byte) do:
  4924.             [:sel | sel ~~ #DoIt ifTrue: [aSortedCollection add: class name , ' ' , sel]]].
  4925.     ^aSortedCollection! !
  4926.  
  4927. !Behavior methodsFor: 'user interface' stamp: 'sw 2/23/98 00:48'!
  4928. browse
  4929.     Browser newOnClass: self! !
  4930.  
  4931. !Behavior methodsFor: 'user interface'!
  4932. browseAllAccessesTo: instVarName     "Collection browseAllAccessesTo: 'contents'."
  4933.     "Create and schedule a Message Set browser for all the receiver's methods 
  4934.     or any methods of a subclass that refer to the instance variable name."
  4935.     | coll |
  4936.     coll _ OrderedCollection new.
  4937.     Cursor wait 
  4938.         showWhile: 
  4939.             [self withAllSubclasses do:
  4940.                 [:class | 
  4941.                 (class whichSelectorsAccess: instVarName) do: 
  4942.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]].
  4943.             self allSuperclasses do:
  4944.                 [:class | 
  4945.                 (class whichSelectorsAccess: instVarName) do: 
  4946.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]]].
  4947.     ^ Smalltalk browseMessageList: coll name: 'Accesses to ' , instVarName autoSelect: instVarName! !
  4948.  
  4949. !Behavior methodsFor: 'user interface'!
  4950. browseAllCallsOn: aSymbol 
  4951.     "Create and schedule a Message Set browser for all the methods that call 
  4952.     on aSymbol."
  4953.     | key label |
  4954.     (aSymbol isKindOf: LookupKey)
  4955.             ifTrue: [label _ 'Users of ' , (key _ aSymbol key)]
  4956.             ifFalse: [label _ 'Senders of ' , (key _ aSymbol)].
  4957.     ^ Smalltalk browseMessageList: (self allCallsOn: aSymbol) asSortedCollection
  4958.         name: label autoSelect: key
  4959.  
  4960.     "Number browseAllCallsOn: #/."! !
  4961.  
  4962. !Behavior methodsFor: 'user interface'!
  4963. browseAllStoresInto: instVarName     "Collection browseAllStoresInto: 'contents'."
  4964.     "Create and schedule a Message Set browser for all the receiver's methods 
  4965.     or any methods of a subclass that refer to the instance variable name."
  4966.     | coll |
  4967.     coll _ OrderedCollection new.
  4968.     Cursor wait 
  4969.         showWhile: 
  4970.             [self withAllSubclasses do:
  4971.                 [:class | 
  4972.                 (class whichSelectorsStoreInto: instVarName) do: 
  4973.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]].
  4974.             self allSuperclasses do:
  4975.                 [:class | 
  4976.                 (class whichSelectorsStoreInto: instVarName) do: 
  4977.                     [:sel | sel ~~ #DoIt ifTrue: [coll add: class name , ' ' , sel]]]].
  4978.     ^ Smalltalk browseMessageList: coll name: 'Stores into ' , instVarName autoSelect: instVarName! !
  4979.  
  4980. !Behavior methodsFor: 'user interface'!
  4981. crossReference
  4982.     "Answer an Array of arrays of size 2 whose first element is a message selector in the receiver's method dictionary and whose second element is a set of all message selectors in the method dictionary whose methods send a message with that selector. Subclasses are not included."
  4983.  
  4984.     ^self selectors asSortedCollection asArray collect: [:x |         Array 
  4985.             with: (String with: Character cr), x 
  4986.             with: (self whichSelectorsReferTo: x)]
  4987.  
  4988.     "Point crossReference."! !
  4989.  
  4990. !Behavior methodsFor: 'user interface' stamp: 'sw 2/4/98 15:21'!
  4991. removeUninstantiatedSubclassesSilently
  4992.     "Remove the classes of any subclasses that have neither instances nor subclasses.  Answer the number of bytes reclaimed"
  4993.     "Player removeUninstantiatedSubclassesSilently"
  4994.  
  4995.     | candidatesForRemoval  oldFree |
  4996.  
  4997.     oldFree _ Smalltalk garbageCollect.
  4998.     candidatesForRemoval _
  4999.         self subclasses select: [:c |
  5000.             (c instanceCount = 0) and: [c subclasses size = 0]].
  5001.     candidatesForRemoval do: [:c | c removeFromSystem].
  5002.     ^ Smalltalk garbageCollect - oldFree! !
  5003.  
  5004. !Behavior methodsFor: 'user interface'!
  5005. unreferencedInstanceVariables
  5006.     "Return a list of the instance variables defined in the receiver which are not referenced in the receiver or any of its subclasses.  2/26/96 sw"
  5007.  
  5008.     | any |
  5009.  
  5010.     ^ self instVarNames copy reject:
  5011.         [:ivn | any _ false.
  5012.         self withAllSubclasses do:
  5013.             [:class |  (class whichSelectorsAccess: ivn) do: 
  5014.                     [:sel | sel ~~ #DoIt ifTrue: [any _ true]]].
  5015.         any]
  5016.  
  5017. "Ob unreferencedInstanceVariables"! !
  5018.  
  5019.  
  5020. !Behavior methodsFor: 'private'!
  5021. becomeCompact
  5022.     | cct index |
  5023.     cct _ Smalltalk compactClassesArray.
  5024.     (self indexIfCompact > 0 or: [cct includes: self])
  5025.         ifTrue: [^ self halt: self name , 'is already compact'].
  5026.     index _ cct indexOf: nil
  5027.         ifAbsent: [^ self halt: 'compact class table is full'].
  5028.     "Install this class in the compact class table"
  5029.     cct at: index put: self.
  5030.     "Update instspec so future instances will be compact"
  5031.     format _ format + (index bitShift: 11).
  5032.     "Make up new instances and become old ones into them"
  5033.     self updateInstancesFrom: self.
  5034.     "Purge any old instances"
  5035.     Smalltalk garbageCollect.! !
  5036.  
  5037. !Behavior methodsFor: 'private'!
  5038. becomeUncompact
  5039.     | cct index |
  5040.     cct _ Smalltalk compactClassesArray.
  5041.     (index _ self indexIfCompact) = 0
  5042.         ifTrue: [^ self].
  5043.     (cct includes: self)
  5044.         ifFalse: [^ self halt  "inconsistent state"].
  5045.     "Update instspec so future instances will not be compact"
  5046.     format _ format - (index bitShift: 11).
  5047.     "Make up new instances and become old ones into them"
  5048.     self updateInstancesFrom: self.
  5049.     "Make sure there are no compact ones left around"
  5050.     Smalltalk garbageCollect.
  5051.     "Remove this class from the compact class table"
  5052.     cct at: index put: nil.
  5053. ! !
  5054.  
  5055. !Behavior methodsFor: 'private'!
  5056. flushCache
  5057.     "Tell the interpreter to remove the contents of its method lookup cache, if it has 
  5058.     one.  Essential.  See Object documentation whatIsAPrimitive."
  5059.  
  5060.     <primitive: 89>
  5061.     self primitiveFailed! !
  5062.  
  5063. !Behavior methodsFor: 'private'!
  5064. format: nInstVars variable: isVar words: isWords pointers: isPointers 
  5065.     "Set the format for the receiver (a Class)."
  5066.     | cClass instSpec sizeHiBits |
  5067.     self flag: #instSizeChange.
  5068. "
  5069. Smalltalk browseAllCallsOn: #instSizeChange.
  5070. Smalltalk browseAllImplementorsOf: #fixedFieldsOf:.
  5071. Smalltalk browseAllImplementorsOf: #instantiateClass:indexableSize:.
  5072. "
  5073. "
  5074.     NOTE: This code supports the backward-compatible extension to 8 bits of instSize.
  5075.     For now the format word is...
  5076.         <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec><6 bits=instSize\\64><1 bit=0>
  5077.     But when we revise the image format, it should become...
  5078.         <5 bits=cClass><4 bits=instSpec><8 bits=instSize><1 bit=0>
  5079. "
  5080.     sizeHiBits _ (nInstVars+1) // 64.
  5081.     cClass _ 0.  "for now"
  5082.     instSpec _ isPointers
  5083.         ifTrue: [isVar
  5084.                 ifTrue: [nInstVars>0 ifTrue: [3] ifFalse: [2]]
  5085.                 ifFalse: [nInstVars>0 ifTrue: [1] ifFalse: [0]]]
  5086.         ifFalse: [isWords ifTrue: [6] ifFalse: [8]].
  5087.     format _ sizeHiBits.
  5088.     format _ (format bitShift: 5) + cClass.
  5089.     format _ (format bitShift: 4) + instSpec.
  5090.     format _ (format bitShift: 6) + ((nInstVars+1)\\64).  "+1 since prim size field includes header"
  5091.     format _ (format bitShift: 1) "This shift plus integer bit lets wordSize work like byteSize"
  5092. ! !
  5093.  
  5094. !Behavior methodsFor: 'private'!
  5095. indexIfCompact
  5096.     "If these 5 bits are non-zero, then instances of this class
  5097.     will be compact.  It is crucial that there be an entry in
  5098.     Smalltalk compactClassesArray for any class so optimized.
  5099.     See the msgs becomeCompact and becomeUncompact."
  5100.     ^ (format bitShift: -11) bitAnd: 16r1F
  5101. "
  5102. Smalltalk compactClassesArray doWithIndex: 
  5103.     [:c :i | c == nil ifFalse:
  5104.         [c indexIfCompact = i ifFalse: [self halt]]]
  5105. "! !
  5106.  
  5107. !Behavior methodsFor: 'private'!
  5108. printSubclassesOn: aStream level: level 
  5109.     "As part of the algorithm for printing a description of the receiver, print the
  5110.     subclass on the file stream, aStream, indenting level times."
  5111.  
  5112.     | subclassNames subclass |
  5113.     aStream crtab: level.
  5114.     aStream nextPutAll: self name.
  5115.     aStream space; print: self instVarNames.
  5116.     self == Class
  5117.         ifTrue: 
  5118.             [aStream crtab: level + 1; nextPutAll: '[ ... all the Metaclasses ... ]'.
  5119.             ^self].
  5120.     subclassNames _ self subclasses collect: [:subC | subC name].
  5121.     "Print subclasses in alphabetical order"
  5122.     subclassNames asSortedCollection do:
  5123.         [:name |
  5124.         subclass _ self subclasses detect: [:subC | subC name = name].
  5125.         subclass printSubclassesOn: aStream level: level + 1]! !
  5126.  
  5127. !Behavior methodsFor: 'private' stamp: 'di 12/26/97 11:07'!
  5128. removeSelectorSimply: selector 
  5129.     "Remove the message selector from the receiver's method dictionary.
  5130.     Internal access from compiler."
  5131.  
  5132.     methodDict removeKey: selector ifAbsent: [^self].
  5133.     selector flushCache! !
  5134. Object subclass: #BitBlt
  5135.     instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight colorMap '
  5136.     classVariableNames: ''
  5137.     poolDictionaries: ''
  5138.     category: 'Graphics-Support'!
  5139. !BitBlt commentStamp: 'di 5/22/1998 16:32' prior: 0!
  5140. BitBlt comment:
  5141. 'I represent a block transfer (BLT) of pixels into a rectangle (destX, destY, width, height) of the destinationForm.  The source of pixels may be a similar rectangle (at sourceX, sourceY) in the sourceForm, or a constant color, currently called halftoneForm.  If both are specified, their pixel values are combined with a logical AND function prior to transfer.  In any case, the pixels from the source are combined with those of the destination by as specified by the combinationRule.
  5142.  
  5143. The combination rule whose value is 0 through 15 programs the transfer to produce 1 or 0 according to its 4-bit representation as follows:
  5144.     8:    if source is 0 and destination is 0
  5145.     4:    if source is 0 and destination is 1
  5146.     2:    if source is 1 and destination is 0
  5147.     1:    if source is 1 and destination is 1.
  5148. At each pixel the corresponding bits of the source and destination pixel values determine one of these conditions;  if the combination rule has a 1 in the corresponding bit position, then the new destination value will be 1, otherwise it will be zero.  Forms may be of different depths, see the comment in class Form.
  5149.  
  5150. In addition to the original 16 combination rules, this BitBlt supports
  5151.     16    fails (to simulate paint bits)
  5152.     17    fails (to simulate erase bits)
  5153.     18    sourceWord + destinationWord
  5154.     19    sourceWord - destinationWord
  5155.     20    rgbAdd: sourceWord with: destinationWord.  Sum of color components
  5156.     21    rgbSub: sourceWord with: destinationWord.  Sum of color components
  5157.     22    rgbDiff: sourceWord with: destinationWord.  Sum of abs of differences in components
  5158.     23    tallyIntoMap: destinationWord
  5159.     24    alphaBlend: sourceWord with: destinationWord
  5160.     25    pixPaint: sourceWord with: destinationWord.  Wherever the sourceForm is non-zero, it replaces the destination.  Can be used with a 1-bit source color mapped to (0, FFFFFFFF), and a fillColor to fill the dest with that color wherever the source is 1.
  5161.     26    pixMask: sourceWord with: destinationWord.  Like pixPaint, but fills with 0.
  5162.     27    rgbMax: sourceWord with: destinationWord.  Max of each color component.
  5163.     28    rgbMin: sourceWord with: destinationWord.  Min of each color component.
  5164.     29    rgbMin: sourceWord bitInvert32 with: destinationWord.  Min with (max-source)
  5165.  
  5166. The color specified by halftoneForm may be either a Color or a Pattern.   A Color is converted to a pixelValue for the depth of the destinationForm.  If a Pattern, BitBlt will simply interpret its bitmap as an array of Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary.  Within each scan line the 32-bit value is repeated from left to right across the form.  If the value repeats on pixels boudaries, the effect will be a constant color;  if not, it will produce a halftone that repeats on 32-bit boundaries.
  5167.  
  5168. Any transfer specified is further clipped by the specified rectangle (clipX, clipY, clipWidth, clipHeight), and also by the bounds of the source and destination forms.
  5169.     To make a small Form repeat and fill a big form, use an InfiniteForm as the source.
  5170.     To write on a form and leave with both transparent and opapue areas, use a MaskedForm as the source.
  5171.  
  5172. Pixels from a source to a destination whose pixels have a different depth are converted based on the optional colorMap.  If colorMap is nil, then conversion to more bits is done by filling the new high-order bits with zero, and conversion to fewer bits is done by truncating the lost high-order bits.  The colorMap, if specified, must be a word array (ie Bitmap) with 2^n elements, where n is the pixel depth of the source.  For every source pixel, BitBlt will then index this array, and select the corresponding pixelValue and mask it to the destination pixel size before storing.
  5173.     When blitting from a 32 or 16 bit deep Form to one 8 bits or less, the default is truncation.  This will produce very strange colors, since truncation of the high bits does not produce the nearest encoded color.  Supply a 512 long colorMap, and red, green, and blue will be shifted down to 3 bits each, and mapped.  The message copybits...stdColors will use the best map to the standard colors for destinations of depths 8, 4, 2 and 1.  Two other sized of colorMaps are allowed, 4096 (4 bits per color) and 32786 (five bits per color).
  5174.     Normal blits between 16 and 32 bit forms truncates or pads the colors automatically to provide the best preservation of colors.
  5175.     Colors can be remapped at the same depth.  Sometimes a Form is in terms of colors that are not the standard colors for this depth, for example in a GIF file.  Convert the Form to a MaskedForm and send colorMap: the list of colors that the picture is in terms of.  MaskedForm will use the colorMap when copying to the display or another Form. (Note also that a Form can be copied to itself, and transformed in the process, if a non-nil colorMap is supplied.)'!
  5176.  
  5177.  
  5178. !BitBlt methodsFor: 'accessing'!
  5179. clipHeight: anInteger 
  5180.     "Set the receiver's clipping area height to be the argument, anInteger."
  5181.  
  5182.     clipHeight _ anInteger! !
  5183.  
  5184. !BitBlt methodsFor: 'accessing'!
  5185. clipRect
  5186.     "Answer the receiver's clipping area rectangle."
  5187.  
  5188.     ^clipX @ clipY extent: clipWidth @ clipHeight! !
  5189.  
  5190. !BitBlt methodsFor: 'accessing'!
  5191. clipRect: aRectangle 
  5192.     "Set the receiver's clipping area rectangle to be the argument, aRectangle."
  5193.  
  5194.     clipX _ aRectangle left.
  5195.     clipY _ aRectangle top.
  5196.     clipWidth _ aRectangle width.
  5197.     clipHeight _ aRectangle height! !
  5198.  
  5199. !BitBlt methodsFor: 'accessing'!
  5200. clipWidth: anInteger 
  5201.     "Set the receiver's clipping area width to be the argument, anInteger."
  5202.  
  5203.     clipWidth _ anInteger! !
  5204.  
  5205. !BitBlt methodsFor: 'accessing'!
  5206. clipX: anInteger 
  5207.     "Set the receiver's clipping area top left x coordinate to be the argument, 
  5208.     anInteger."
  5209.  
  5210.     clipX _ anInteger! !
  5211.  
  5212. !BitBlt methodsFor: 'accessing'!
  5213. clipY: anInteger 
  5214.     "Set the receiver's clipping area top left y coordinate to be the argument, 
  5215.     anInteger."
  5216.  
  5217.     clipY _ anInteger! !
  5218.  
  5219. !BitBlt methodsFor: 'accessing'!
  5220. colorMap
  5221.     ^ colorMap! !
  5222.  
  5223. !BitBlt methodsFor: 'accessing'!
  5224. colorMap: map
  5225.     "See last part of BitBlt comment. 6/18/96 tk"
  5226.     colorMap _ map! !
  5227.  
  5228. !BitBlt methodsFor: 'accessing'!
  5229. combinationRule: anInteger 
  5230.     "Set the receiver's combination rule to be the argument, anInteger, a 
  5231.     number in the range 0-15."
  5232.  
  5233.     combinationRule _ anInteger! !
  5234.  
  5235. !BitBlt methodsFor: 'accessing'!
  5236. destForm
  5237.     ^ destForm! !
  5238.  
  5239. !BitBlt methodsFor: 'accessing'!
  5240. destOrigin: aPoint 
  5241.     "Set the receiver's destination top left coordinates to be those of the 
  5242.     argument, aPoint."
  5243.  
  5244.     destX _ aPoint x.
  5245.     destY _ aPoint y! !
  5246.  
  5247. !BitBlt methodsFor: 'accessing' stamp: 'tk 3/19/97'!
  5248. destRect
  5249.     "The rectangle we are about to blit to or just blitted to.  "
  5250.  
  5251.     ^ destX @ destY extent: width @ height! !
  5252.  
  5253. !BitBlt methodsFor: 'accessing'!
  5254. destRect: aRectangle 
  5255.     "Set the receiver's destination form top left coordinates to be the origin of 
  5256.     the argument, aRectangle, and set the width and height of the receiver's 
  5257.     destination form to be the width and height of aRectangle."
  5258.  
  5259.     destX _ aRectangle left.
  5260.     destY _ aRectangle top.
  5261.     width _ aRectangle width.
  5262.     height _ aRectangle height! !
  5263.  
  5264. !BitBlt methodsFor: 'accessing'!
  5265. destX: anInteger 
  5266.     "Set the top left x coordinate of the receiver's destination form to be the 
  5267.     argument, anInteger."
  5268.  
  5269.     destX _ anInteger! !
  5270.  
  5271. !BitBlt methodsFor: 'accessing'!
  5272. destX: x destY: y width: w height: h
  5273.     "Combined init message saves 3 sends from DisplayScanner"
  5274.     destX _ x.
  5275.     destY _ y.
  5276.     width _ w.
  5277.     height _ h.! !
  5278.  
  5279. !BitBlt methodsFor: 'accessing'!
  5280. destY: anInteger 
  5281.     "Set the top left y coordinate of the receiver's destination form to be the 
  5282.     argument, anInteger."
  5283.  
  5284.     destY _ anInteger! !
  5285.  
  5286. !BitBlt methodsFor: 'accessing'!
  5287. fillColor
  5288.     ^ halftoneForm! !
  5289.  
  5290. !BitBlt methodsFor: 'accessing'!
  5291. fillColor: aColorOrPattern 
  5292.     "The destForm will be filled with this color or pattern of colors.  May be an old Color, a new type Color, a Bitmap (see BitBlt comment), a Pattern, or a Form.  6/18/96 tk"
  5293.  
  5294.     aColorOrPattern == nil ifTrue: [halftoneForm _ nil. ^ self].
  5295.     destForm == nil ifTrue: [self error: 'Must set destForm first'].
  5296.     halftoneForm _ aColorOrPattern bitPatternForDepth: destForm depth! !
  5297.  
  5298. !BitBlt methodsFor: 'accessing'!
  5299. height: anInteger 
  5300.     "Set the receiver's destination form height to be the argument, anInteger."
  5301.  
  5302.     height _ anInteger! !
  5303.  
  5304. !BitBlt methodsFor: 'accessing'!
  5305. sourceForm
  5306.  
  5307.     ^ sourceForm! !
  5308.  
  5309. !BitBlt methodsFor: 'accessing'!
  5310. sourceForm: aForm 
  5311.     "Set the receiver's source form to be the argument, aForm."
  5312.  
  5313.     sourceForm _ aForm! !
  5314.  
  5315. !BitBlt methodsFor: 'accessing'!
  5316. sourceOrigin: aPoint 
  5317.     "Set the receiver's source form coordinates to be those of the argument, 
  5318.     aPoint."
  5319.  
  5320.     sourceX _ aPoint x.
  5321.     sourceY _ aPoint y! !
  5322.  
  5323. !BitBlt methodsFor: 'accessing'!
  5324. sourceRect: aRectangle 
  5325.     "Set the receiver's source form top left x and y, width and height to be 
  5326.     the top left coordinate and extent of the argument, aRectangle."
  5327.  
  5328.     sourceX _ aRectangle left.
  5329.     sourceY _ aRectangle top.
  5330.     width _ aRectangle width.
  5331.     height _ aRectangle height! !
  5332.  
  5333. !BitBlt methodsFor: 'accessing'!
  5334. sourceX: anInteger 
  5335.     "Set the receiver's source form top left x to be the argument, anInteger."
  5336.  
  5337.     sourceX _ anInteger! !
  5338.  
  5339. !BitBlt methodsFor: 'accessing'!
  5340. sourceY: anInteger 
  5341.     "Set the receiver's source form top left y to be the argument, anInteger."
  5342.  
  5343.     sourceY _ anInteger! !
  5344.  
  5345. !BitBlt methodsFor: 'accessing'!
  5346. width: anInteger 
  5347.     "Set the receiver's destination form width to be the argument, anInteger."
  5348.  
  5349.     width _ anInteger! !
  5350.  
  5351.  
  5352. !BitBlt methodsFor: 'copying'!
  5353. copy: destRectangle from: sourcePt in: srcForm
  5354.     | destOrigin |
  5355.     sourceForm _ srcForm.
  5356.     halftoneForm _ nil.
  5357.     combinationRule _ 3.  "store"
  5358.     destOrigin _ destRectangle origin.
  5359.     destX _ destOrigin x.
  5360.     destY _ destOrigin y.
  5361.     sourceX _ sourcePt x.
  5362.     sourceY _ sourcePt y.
  5363.     width _ destRectangle width.
  5364.     height _ destRectangle height.
  5365.     self copyBits! !
  5366.  
  5367. !BitBlt methodsFor: 'copying'!
  5368. copy: destRectangle from: sourcePt in: srcForm fillColor: hf rule: rule
  5369.     "Specify a Color to fill, not a Form. 6/18/96 tk"  
  5370.     | destOrigin |
  5371.     sourceForm _ srcForm.
  5372.     self fillColor: hf.    "sets halftoneForm"
  5373.     combinationRule _ rule.
  5374.     destOrigin _ destRectangle origin.
  5375.     destX _ destOrigin x.
  5376.     destY _ destOrigin y.
  5377.     sourceX _ sourcePt x.
  5378.     sourceY _ sourcePt y.
  5379.     width _ destRectangle width.
  5380.     height _ destRectangle height.
  5381.     ^ self copyBits! !
  5382.  
  5383. !BitBlt methodsFor: 'copying'!
  5384. copy: destRectangle from: sourcePt in: srcForm halftoneForm: hf rule: rule 
  5385.     | destOrigin |
  5386.     sourceForm _ srcForm.
  5387.     self fillColor: hf.        "sets halftoneForm"
  5388.     combinationRule _ rule.
  5389.     destOrigin _ destRectangle origin.
  5390.     destX _ destOrigin x.
  5391.     destY _ destOrigin y.
  5392.     sourceX _ sourcePt x.
  5393.     sourceY _ sourcePt y.
  5394.     width _ destRectangle width.
  5395.     height _ destRectangle height.
  5396.     self copyBits! !
  5397.  
  5398. !BitBlt methodsFor: 'copying' stamp: 'di 3/2/98 14:06'!
  5399. copyBits
  5400.     "Primitive. Perform the movement of bits from the source form to the 
  5401.     destination form. Fail if any variables are not of the right type (Integer, 
  5402.     Float, or Form) or if the combination rule is not implemented. 
  5403.     In addition to the original 16 combination rules, this BitBlt supports
  5404.     16    fail (to simulate paint)
  5405.     17    fail (to simulate mask)
  5406.     18    sourceWord + destinationWord
  5407.     19    sourceWord - destinationWord
  5408.     20    rgbAdd: sourceWord with: destinationWord
  5409.     21    rgbSub: sourceWord with: destinationWord
  5410.     22    rgbDiff: sourceWord with: destinationWord
  5411.     23    tallyIntoMap: destinationWord
  5412.     24    alphaBlend: sourceWord with: destinationWord
  5413.     25    pixPaint: sourceWord with: destinationWord
  5414.     26    pixMask: sourceWord with: destinationWord
  5415.     27    rgbMax: sourceWord with: destinationWord
  5416.     28    rgbMin: sourceWord with: destinationWord
  5417.     29    rgbMin: sourceWord bitInvert32 with: destinationWord
  5418. "
  5419.     <primitive: 96>
  5420.  
  5421.     "Check for compressed source, destination or halftone forms"
  5422.     ((sourceForm isKindOf: Form) and: [sourceForm unhibernate])
  5423.         ifTrue: [^ self copyBits].
  5424.     ((destForm isKindOf: Form) and: [destForm unhibernate])
  5425.         ifTrue: [^ self copyBits].
  5426.     ((halftoneForm isKindOf: Form) and: [halftoneForm unhibernate])
  5427.         ifTrue: [^ self copyBits].
  5428.  
  5429.     "Check for unimplmented rules"
  5430.     combinationRule = Form oldPaint ifTrue: [^ self paintBits].
  5431.     combinationRule = Form oldErase1bitShape ifTrue: [^ self eraseBits].
  5432.  
  5433.     self halt: 'Bad BitBlt arg (Fraction?); proceed to convert.'.
  5434.     "Convert all numeric parameters to integers and try again."
  5435.     destX _ destX asInteger.
  5436.     destY _ destY asInteger.
  5437.     width _ width asInteger.
  5438.     height _ height asInteger.
  5439.     sourceX _ sourceX asInteger.
  5440.     sourceY _ sourceY asInteger.
  5441.     clipX _ clipX asInteger.
  5442.     clipY _ clipY asInteger.
  5443.     clipWidth _ clipWidth asInteger.
  5444.     clipHeight _ clipHeight asInteger.
  5445.     ^ self copyBitsAgain! !
  5446.  
  5447. !BitBlt methodsFor: 'copying' stamp: 'di 7/17/97 10:04'!
  5448. copyForm: srcForm to: destPt rule: rule
  5449.     ^ self copyForm: srcForm to: destPt rule: rule
  5450.         colorMap: (srcForm colormapIfNeededForDepth: destForm depth)! !
  5451.  
  5452. !BitBlt methodsFor: 'copying'!
  5453. copyForm: srcForm to: destPt rule: rule color: color
  5454.     sourceForm _ srcForm.
  5455.     halftoneForm _ color.
  5456.     combinationRule _ rule.
  5457.     destX _ destPt x + sourceForm offset x.
  5458.     destY _ destPt y + sourceForm offset y.
  5459.     sourceX _ 0.
  5460.     sourceY _ 0.
  5461.     width _ sourceForm width.
  5462.     height _ sourceForm height.
  5463.     self copyBits! !
  5464.  
  5465. !BitBlt methodsFor: 'copying' stamp: 'di 7/17/97 10:04'!
  5466. copyForm: srcForm to: destPt rule: rule colorMap: map
  5467.     sourceForm _ srcForm.
  5468.     halftoneForm _ nil.
  5469.     combinationRule _ rule.
  5470.     destX _ destPt x + sourceForm offset x.
  5471.     destY _ destPt y + sourceForm offset y.
  5472.     sourceX _ 0.
  5473.     sourceY _ 0.
  5474.     width _ sourceForm width.
  5475.     height _ sourceForm height.
  5476.     colorMap _ map.
  5477.     self copyBits! !
  5478.  
  5479. !BitBlt methodsFor: 'copying'!
  5480. copyForm: srcForm to: destPt rule: rule fillColor: color
  5481.     sourceForm _ srcForm.
  5482.     self fillColor: color.    "sets halftoneForm"
  5483.     combinationRule _ rule.
  5484.     destX _ destPt x + sourceForm offset x.
  5485.     destY _ destPt y + sourceForm offset y.
  5486.     sourceX _ 0.
  5487.     sourceY _ 0.
  5488.     width _ sourceForm width.
  5489.     height _ sourceForm height.
  5490.     self copyBits! !
  5491.  
  5492. !BitBlt methodsFor: 'copying' stamp: 'di 7/1/97 14:09'!
  5493. copyFrom: sourceRectangle in: srcForm to: destPt
  5494.     | sourceOrigin |
  5495.     sourceForm _ srcForm.
  5496.     halftoneForm _ nil.
  5497.     combinationRule _ 3.  "store"
  5498.     destX _ destPt x.
  5499.     destY _ destPt y.
  5500.     sourceOrigin _ sourceRectangle origin.
  5501.     sourceX _ sourceOrigin x.
  5502.     sourceY _ sourceOrigin y.
  5503.     width _ sourceRectangle width.
  5504.     height _ sourceRectangle height.
  5505.     colorMap _ srcForm colormapIfNeededForDepth: destForm depth.
  5506.     self copyBits! !
  5507.  
  5508. !BitBlt methodsFor: 'copying'!
  5509. fill: destRect fillColor: grayForm rule: rule
  5510.     "Fill with a Color, not a Form. 6/18/96 tk"
  5511.     sourceForm _ nil.
  5512.     self fillColor: grayForm.        "sets halftoneForm"
  5513.     combinationRule _ rule.
  5514.     destX _ destRect left.
  5515.     destY _ destRect top.
  5516.     sourceX _ 0.
  5517.     sourceY _ 0.
  5518.     width _ destRect width.
  5519.     height _ destRect height.
  5520.     self copyBits! !
  5521.  
  5522. !BitBlt methodsFor: 'copying'!
  5523. pixelAt: aPoint
  5524.     "Assumes this BitBlt has been set up specially (see the init message,
  5525.     BitBlt bitPeekerFromForm:.  Returns the pixel at aPoint."
  5526.     sourceX _ aPoint x.
  5527.     sourceY _ aPoint y.
  5528.     destForm bits at: 1 put: 0.  "Just to be sure"
  5529.     self copyBits.
  5530.     ^ destForm bits at: 1! !
  5531.  
  5532. !BitBlt methodsFor: 'copying'!
  5533. pixelAt: aPoint put: pixelValue
  5534.     "Assumes this BitBlt has been set up specially (see the init message,
  5535.     BitBlt bitPokerToForm:.  Overwrites the pixel at aPoint."
  5536.     destX _ aPoint x.
  5537.     destY _ aPoint y.
  5538.     sourceForm bits at: 1 put: pixelValue.
  5539.     self copyBits
  5540. "
  5541. | bb |
  5542. bb _ (BitBlt bitPokerToForm: Display).
  5543. [Sensor anyButtonPressed] whileFalse:
  5544.     [bb pixelAt: Sensor cursorPoint put: 55]
  5545. "! !
  5546.  
  5547.  
  5548. !BitBlt methodsFor: 'line drawing'!
  5549. drawFrom: startPoint to: stopPoint 
  5550.     
  5551.      ^ self drawFrom: startPoint to: stopPoint withFirstPoint: true! !
  5552.  
  5553. !BitBlt methodsFor: 'line drawing' stamp: '6/8/97 15:41 di'!
  5554. drawFrom: startPoint to: stopPoint withFirstPoint: drawFirstPoint
  5555.     "Draw a line whose end points are startPoint and stopPoint.
  5556.     The line is formed by repeatedly calling copyBits at every
  5557.     point along the line.  If drawFirstPoint is false, then omit
  5558.     the first point so as not to overstrike at line junctions."
  5559.     | offset point1 point2 forwards |
  5560.     "Always draw down, or at least left-to-right"
  5561.     forwards _ (startPoint y = stopPoint y and: [startPoint x < stopPoint x])
  5562.                 or: [startPoint y < stopPoint y].
  5563.     forwards
  5564.         ifTrue: [point1 _ startPoint. point2 _ stopPoint]
  5565.         ifFalse: [point1 _ stopPoint. point2 _ startPoint].
  5566.     sourceForm == nil ifTrue:
  5567.         [destX _ point1 x.
  5568.         destY _ point1 y]
  5569.         ifFalse:
  5570.         [width _ sourceForm width.
  5571.         height _ sourceForm height.
  5572.         offset _ sourceForm offset.
  5573.         destX _ (point1 x + offset x) rounded.
  5574.         destY _ (point1 y + offset y) rounded].
  5575.  
  5576.     "Note that if not forwards, then the first point is the last and vice versa.
  5577.     We agree to always paint stopPoint, and to optionally paint startPoint."
  5578.     (drawFirstPoint or: [forwards == false  "ie this is stopPoint"])
  5579.         ifTrue: [self copyBits].
  5580.     self drawLoopX: (point2 x - point1 x) rounded 
  5581.                   Y: (point2 y - point1 y) rounded.
  5582.     (drawFirstPoint or: [forwards  "ie this is stopPoint"])
  5583.         ifTrue: [self copyBits].
  5584. ! !
  5585.  
  5586. !BitBlt methodsFor: 'line drawing'!
  5587. drawLoopX: xDelta Y: yDelta 
  5588.     "Primitive. Implements the Bresenham plotting algorithm (IBM Systems
  5589.     Journal, Vol. 4 No. 1, 1965). It chooses a principal direction, and
  5590.     maintains a potential, P. When P's sign changes, it is time to move in
  5591.     the minor direction as well. This particular version does not write the
  5592.     first and last points, so that these can be called for as needed in client code.
  5593.     Optional. See Object documentation whatIsAPrimitive."
  5594.     | dx dy px py P |
  5595.     <primitive: 104>
  5596.     dx _ xDelta sign.
  5597.     dy _ yDelta sign.
  5598.     px _ yDelta abs.
  5599.     py _ xDelta abs.
  5600.     "self copyBits."
  5601.     py > px
  5602.         ifTrue: 
  5603.             ["more horizontal"
  5604.             P _ py // 2.
  5605.             1 to: py do: 
  5606.                 [:i |
  5607.                 destX _ destX + dx.
  5608.                 (P _ P - px) < 0 ifTrue: 
  5609.                         [destY _ destY + dy.
  5610.                         P _ P + py].
  5611.                 i < py ifTrue: [self copyBits]]]
  5612.         ifFalse: 
  5613.             ["more vertical"
  5614.             P _ px // 2.
  5615.             1 to: px do:
  5616.                 [:i |
  5617.                 destY _ destY + dy.
  5618.                 (P _ P - py) < 0 ifTrue: 
  5619.                         [destX _ destX + dx.
  5620.                         P _ P + px].
  5621.                 i < px ifTrue: [self copyBits]]]! !
  5622.  
  5623.  
  5624. !BitBlt methodsFor: 'private'!
  5625. copyBitsAgain
  5626.     "Primitive. See BitBlt|copyBits, also a Primitive. Essential. See Object
  5627.     documentation whatIsAPrimitive."
  5628.  
  5629.     <primitive: 96>
  5630.     self primitiveFailed! !
  5631.  
  5632. !BitBlt methodsFor: 'private'!
  5633. eraseBits
  5634.     "Perform the erase operation, which puts 0's in the destination
  5635.     wherever the source (which is assumed to be just 1 bit deep)
  5636.     has a 1.  This requires the colorMap to be set in order to AND
  5637.     all 1's into the destFrom pixels regardless of their size."
  5638.     | oldMask oldMap |
  5639.     oldMask _ halftoneForm.
  5640.     halftoneForm _ nil.
  5641.     oldMap _ colorMap.
  5642.     self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
  5643.     combinationRule _ Form erase.
  5644.     self copyBits.         "Erase the dest wherever the source is 1"
  5645.     halftoneForm _ oldMask.    "already converted to a Bitmap"
  5646.     colorMap _ oldMap! !
  5647.  
  5648. !BitBlt methodsFor: 'private'!
  5649. paintBits
  5650.     "Perform the paint operation, which requires two calls to BitBlt."
  5651.     | color oldMap saveRule |
  5652.     sourceForm depth = 1 ifFalse: 
  5653.         [^ self halt: 'paint operation is only defined for 1-bit deep sourceForms'].
  5654.     saveRule _ combinationRule.
  5655.     color _ halftoneForm.  halftoneForm _ nil.
  5656.     oldMap _ colorMap.
  5657.     "Map 1's to ALL ones, not just one"
  5658.     self colorMap: (Bitmap with: 0 with: 16rFFFFFFFF).
  5659.     combinationRule _ Form erase.
  5660.     self copyBits.         "Erase the dest wherever the source is 1"
  5661.     halftoneForm _ color.
  5662.     combinationRule _ Form under.
  5663.     self copyBits.    "then OR, with whatever color, into the hole"
  5664.     colorMap _ oldMap.
  5665.     combinationRule _ saveRule
  5666.  
  5667. " | dot |
  5668. dot _ Form dotOfSize: 32.
  5669. ((BitBlt destForm: Display
  5670.         sourceForm: dot
  5671.         fillColor: Color lightGray
  5672.         combinationRule: Form paint
  5673.         destOrigin: Sensor cursorPoint
  5674.         sourceOrigin: 0@0
  5675.         extent: dot extent
  5676.         clipRect: Display boundingBox)
  5677.         colorMap: (Bitmap with: 0 with: 16rFFFFFFFF)) copyBits"! !
  5678.  
  5679. !BitBlt methodsFor: 'private'!
  5680. setDestForm: df
  5681.     | bb |
  5682.     bb _ df boundingBox.
  5683.     destForm _ df.
  5684.     clipX _ bb left.
  5685.     clipY _ bb top.
  5686.     clipWidth _ bb width.
  5687.     clipHeight _ bb height! !
  5688.  
  5689. !BitBlt methodsFor: 'private'!
  5690. setDestForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect
  5691.  
  5692.     | aPoint |
  5693.     destForm _ df.
  5694.     sourceForm _ sf.
  5695.     self fillColor: hf.    "sets halftoneForm"
  5696.     combinationRule _ cr.
  5697.     destX _ destOrigin x.
  5698.     destY _ destOrigin y.
  5699.     sourceX _ sourceOrigin x.
  5700.     sourceY _ sourceOrigin y.
  5701.     width _ extent x.
  5702.     height _ extent y.
  5703.     aPoint _ clipRect origin.
  5704.     clipX _ aPoint x.
  5705.     clipY _ aPoint y.
  5706.     aPoint _ clipRect corner.
  5707.     clipWidth _ aPoint x - clipX.
  5708.     clipHeight _ aPoint y - clipY.
  5709.     colorMap _ sourceForm colormapIfNeededForDepth: destForm depth.
  5710. ! !
  5711.  
  5712. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  5713.  
  5714. BitBlt class
  5715.     instanceVariableNames: ''!
  5716.  
  5717. !BitBlt class methodsFor: 'instance creation' stamp: 'di 3/2/98 12:53'!
  5718. bitPeekerFromForm: sourceForm
  5719.     "Answer an instance to be used extract individual pixels from the given Form. The destination for a 1x1 copyBits will be the low order bits of (bits at: 1)."
  5720.     | pixPerWord |
  5721.     pixPerWord _ 32 // sourceForm depth.
  5722.     sourceForm unhibernate.
  5723.     ^ self destForm: (Form extent: pixPerWord@1 depth: sourceForm depth)
  5724.          sourceForm: sourceForm
  5725.         halftoneForm: nil
  5726.         combinationRule: Form over
  5727.         destOrigin: (pixPerWord - 1)@0
  5728.         sourceOrigin: 0@0
  5729.         extent: 1@1
  5730.         clipRect: (0@0 extent: pixPerWord@1)
  5731. ! !
  5732.  
  5733. !BitBlt class methodsFor: 'instance creation' stamp: 'di 3/2/98 12:53'!
  5734. bitPokerToForm: destForm
  5735.     "Answer an instance to be used for valueAt: aPoint put: pixValue.
  5736.     The source for a 1x1 copyBits will be the low order of (bits at: 1)"
  5737.     | pixPerWord |
  5738.     pixPerWord _ 32//destForm depth.
  5739.     destForm unhibernate.
  5740.     ^ self destForm: destForm
  5741.          sourceForm: (Form extent: pixPerWord@1 depth: destForm depth)
  5742.         halftoneForm: nil combinationRule: Form over
  5743.         destOrigin: 0@0 sourceOrigin: (pixPerWord-1)@0
  5744.         extent: 1@1 clipRect: (0@0 extent: destForm extent)
  5745. ! !
  5746.  
  5747. !BitBlt class methodsFor: 'instance creation'!
  5748. destForm: df sourceForm: sf fillColor: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect 
  5749.     "Answer an instance of me with values set according to the arguments."
  5750.  
  5751.     ^ self new
  5752.         setDestForm: df
  5753.         sourceForm: sf
  5754.         fillColor: hf
  5755.         combinationRule: cr
  5756.         destOrigin: destOrigin
  5757.         sourceOrigin: sourceOrigin
  5758.         extent: extent
  5759.         clipRect: clipRect! !
  5760.  
  5761. !BitBlt class methodsFor: 'instance creation'!
  5762. destForm: df sourceForm: sf halftoneForm: hf combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin extent: extent clipRect: clipRect 
  5763.     "Answer an instance of me with values set according to the arguments."
  5764.  
  5765.     ^ self new
  5766.         setDestForm: df
  5767.         sourceForm: sf
  5768.         fillColor: hf
  5769.         combinationRule: cr
  5770.         destOrigin: destOrigin
  5771.         sourceOrigin: sourceOrigin
  5772.         extent: extent
  5773.         clipRect: clipRect! !
  5774.  
  5775. !BitBlt class methodsFor: 'instance creation'!
  5776. toForm: aForm
  5777.     ^ self new setDestForm: aForm! !
  5778.  
  5779.  
  5780. !BitBlt class methodsFor: 'examples' stamp: 'di 12/1/97 12:08'!
  5781. alphaBlendDemo
  5782.     "To run this demo, use...
  5783.         Display restoreAfter: [BitBlt alphaBlendDemo]    
  5784.     Displays 10 alphas, then lets you paint.  Option-Click to stop painting."
  5785.  
  5786.     "This code exhibits alpha blending in any display depth by performing
  5787.     the blend in an off-screen buffer with 32-bit pixels, and then copying
  5788.     the result back onto the screen with an appropriate color map. - tk 3/10/97"
  5789.     
  5790.     "This version uses a sliding buffer for painting that keeps pixels in 32 bits
  5791.     as long as they are in the buffer, so as not to lose info by converting down
  5792.     to display resolution and back up to 32 bits at each operation. - di 3/15/97"
  5793.  
  5794.     | brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect |  
  5795.  
  5796.     "compute color maps if needed"
  5797.     Display depth <= 8 ifTrue: [
  5798.         mapDto32 _ Color cachedColormapFrom: Display depth to: 32.
  5799.         map32toD _ Color cachedColormapFrom: 32 to: Display depth].
  5800.  
  5801.     "display 10 different alphas, across top of screen"
  5802.     buff _ Form extent: 500@50 depth: 32.
  5803.     dispToBuff _ BitBlt toForm: buff.
  5804.     dispToBuff colorMap: mapDto32.
  5805.     dispToBuff copyFrom: (50@10 extent: 500@50) in: Display to: 0@0.
  5806.     1 to: 10 do: [:i | dispToBuff fill: (50*(i-1)@0 extent: 50@50)
  5807.                         fillColor: (Color red alpha: i/10)
  5808.                         rule: Form blend].
  5809.     buffToDisplay _ BitBlt toForm: Display.
  5810.     buffToDisplay colorMap: map32toD.
  5811.     buffToDisplay copyFrom: buff boundingBox in: buff to: 50@10.
  5812.  
  5813.     "Create a brush with radially varying alpha"
  5814.     brush _ Form extent: 30@30 depth: 32.
  5815.     1 to: 5 do: 
  5816.         [:i | brush fillShape: (Form dotOfSize: brush width*(6-i)//5)
  5817.                 fillColor: (Color red alpha: 0.02 * i - 0.01)
  5818.                 at: brush extent // 2].
  5819.  
  5820.     "Now paint with the brush using alpha blending."
  5821.     buffSize _ 100.
  5822.     buff _ Form extent: brush extent + buffSize depth: 32.  "Travelling 32-bit buffer"
  5823.     dispToBuff _ BitBlt toForm: buff.  "This is from Display to buff"
  5824.     dispToBuff colorMap: mapDto32.
  5825.     brushToBuff _ BitBlt toForm: buff.  "This is from brush to buff"
  5826.     brushToBuff sourceForm: brush; sourceOrigin: 0@0.
  5827.     brushToBuff combinationRule: Form blend.
  5828.     buffToBuff _ BitBlt toForm: buff.  "This is for slewing the buffer"
  5829.  
  5830.     [Sensor yellowButtonPressed] whileFalse:
  5831.         [prevP _ nil.
  5832.         buffRect _ Sensor cursorPoint - (buffSize // 2) extent: buff extent.
  5833.         dispToBuff copyFrom: buffRect in: Display to: 0@0.
  5834.         [Sensor redButtonPressed] whileTrue:
  5835.             ["Here is the painting loop"
  5836.             p _ Sensor cursorPoint - (brush extent // 2).
  5837.             (prevP == nil or: [prevP ~= p]) ifTrue:
  5838.                 [prevP == nil ifTrue: [prevP _ p].
  5839.                 (p dist: prevP) > buffSize ifTrue:
  5840.                     ["Stroke too long to fit in buffer -- clip to buffer,
  5841.                         and next time through will do more of it"
  5842.                     theta _ (p-prevP) theta.
  5843.                     p _ ((theta cos@theta sin) * buffSize asFloat + prevP) truncated].
  5844.                 brushRect _ p extent: brush extent.
  5845.                 (buffRect containsRect: brushRect) ifFalse:
  5846.                     ["Brush is out of buffer region.  Scroll the buffer,
  5847.                         and fill vacated regions from the display"
  5848.                     delta _ brushRect amountToTranslateWithin: buffRect.
  5849.                     buffToBuff copyFrom: buff boundingBox in: buff to: delta.
  5850.                     newBuffRect _ buffRect translateBy: delta negated.
  5851.                     (newBuffRect areasOutside: buffRect) do:
  5852.                         [:r | dispToBuff copyFrom: r in: Display to: r origin - newBuffRect origin].
  5853.                     buffRect _ newBuffRect].
  5854.  
  5855.                 "Interpolate from prevP to p..."
  5856.                 brushToBuff drawFrom: prevP - buffRect origin
  5857.                                     to: p - buffRect origin
  5858.                                     withFirstPoint: false.
  5859.  
  5860.                 "Update (only) the altered pixels of the destination"
  5861.                 updateRect _ (p min: prevP) corner: (p max: prevP) + brush extent.
  5862.                 buffToDisplay copy: updateRect from: updateRect origin - buffRect origin in: buff.
  5863.                 prevP _ p]]]! !
  5864.  
  5865. !BitBlt class methodsFor: 'examples' stamp: 'di 12/1/97 12:09'!
  5866. antiAliasDemo 
  5867.     "To run this demo, use...
  5868.         Display restoreAfter: [BitBlt antiAliasDemo]
  5869.     Goes immediately into on-screen paint mode.  Option-Click to stop painting."
  5870.  
  5871.     "This code exhibits alpha blending in any display depth by performing
  5872.     the blend in an off-screen buffer with 32-bit pixels, and then copying
  5873.     the result back onto the screen with an appropriate color map. - tk 3/10/97"
  5874.     
  5875.     "This version uses a sliding buffer for painting that keeps pixels in 32 bits
  5876.     as long as they are in the buffer, so as not to lose info by converting down
  5877.     to display resolution and back up to 32 bits at each operation. - di 3/15/97"
  5878.     
  5879.     "This version also uses WarpBlt to paint into twice as large a buffer,
  5880.     and then use smoothing when reducing back down to the display.
  5881.     In fact this same routine will now work for 3x3 soothing as well.
  5882.     Remove the statements 'buff displayAt: 0@0' to hide the buffer. - di 3/19/97"
  5883.  
  5884.     | brush buff dispToBuff buffToDisplay mapDto32 map32toD prevP p brushToBuff theta buffRect buffSize buffToBuff brushRect delta newBuffRect updateRect scale p0 |  
  5885.     "compute color maps if needed"
  5886.     Display depth <= 8 ifTrue: [
  5887.         mapDto32 _ Color cachedColormapFrom: Display depth to: 32.
  5888.         map32toD _ Color cachedColormapFrom: 32 to: Display depth].
  5889.  
  5890.     "Create a brush with radially varying alpha"
  5891.     brush _ Form extent: 3@3 depth: 32.
  5892.     brush fill: brush boundingBox fillColor: (Color red alpha: 0.05).
  5893.     brush fill: (1@1 extent: 1@1) fillColor: (Color red alpha: 0.2).
  5894.  
  5895.     scale _ 2.  "Actual drawing happens at this magnification"
  5896.     "Scale brush up for painting in magnified buffer"
  5897.     brush _ brush magnify: brush boundingBox by: scale.
  5898.  
  5899.     "Now paint with the brush using alpha blending."
  5900.     buffSize _ 100.
  5901.     buff _ Form extent: (brush extent + buffSize) * scale depth: 32.  "Travelling 32-bit buffer"
  5902.     dispToBuff _ (WarpBlt toForm: buff)  "From Display to buff - magnify by 2"
  5903.         sourceForm: Display;
  5904.         colorMap: mapDto32;
  5905.         combinationRule: Form over.
  5906.     brushToBuff _ (BitBlt toForm: buff)  "From brush to buff"
  5907.         sourceForm: brush;
  5908.         sourceOrigin: 0@0;
  5909.         combinationRule: Form blend.
  5910.     buffToDisplay _ (WarpBlt toForm: Display)  "From buff to Display - shrink by 2"
  5911.         sourceForm: buff;
  5912.         colorMap: map32toD;
  5913.         cellSize: scale;  "...and use smoothing"
  5914.         combinationRule: Form over.
  5915.     buffToBuff _ BitBlt toForm: buff.  "This is for slewing the buffer"
  5916.  
  5917.     [Sensor yellowButtonPressed] whileFalse:
  5918.         [prevP _ nil.
  5919.         buffRect _ Sensor cursorPoint - (buff extent // scale // 2) extent: buff extent // scale.
  5920.         p0 _ (buff extent // 2) - (buffRect extent // 2).
  5921.         dispToBuff copyQuad: buffRect innerCorners toRect: buff boundingBox.
  5922. buff displayAt: 0@0.  "** remove to hide sliding buffer **"
  5923.         [Sensor redButtonPressed] whileTrue:
  5924.             ["Here is the painting loop"
  5925.             p _ Sensor cursorPoint - buffRect origin + p0.  "p, prevP are rel to buff origin"
  5926.             (prevP == nil or: [prevP ~= p]) ifTrue:
  5927.                 [prevP == nil ifTrue: [prevP _ p].
  5928.                 (p dist: prevP) > (buffSize-1) ifTrue:
  5929.                     ["Stroke too long to fit in buffer -- clip to buffer,
  5930.                         and next time through will do more of it"
  5931.                     theta _ (p-prevP) theta.
  5932.                     p _ ((theta cos@theta sin) * (buffSize-2) asFloat + prevP) truncated].
  5933.                 brushRect _ p extent: brush extent.
  5934.                 ((buff boundingBox insetBy: scale) containsRect: brushRect) ifFalse:
  5935.                     ["Brush is out of buffer region.  Scroll the buffer,
  5936.                         and fill vacated regions from the display"
  5937.                     delta _ (brushRect amountToTranslateWithin: (buff boundingBox insetBy: scale)) // scale.
  5938.                     buffToBuff copyFrom: buff boundingBox in: buff to: delta*scale.
  5939.                     newBuffRect _ buffRect translateBy: delta negated.
  5940.                     p _ p translateBy: delta*scale.
  5941.                     prevP _ prevP translateBy: delta*scale.
  5942.                     (newBuffRect areasOutside: buffRect) do:
  5943.                         [:r | dispToBuff copyQuad: r innerCorners toRect: (r origin - newBuffRect origin*scale extent: r extent*scale)].
  5944.                     buffRect _ newBuffRect].
  5945.  
  5946.                 "Interpolate from prevP to p..."
  5947.                 brushToBuff drawFrom: prevP to: p withFirstPoint: false.
  5948. buff displayAt: 0@0.  "** remove to hide sliding buffer **"
  5949.  
  5950.                 "Update (only) the altered pixels of the destination"
  5951.                 updateRect _ (p min: prevP) corner: (p max: prevP) + brush extent.
  5952.                 updateRect _ updateRect origin // scale * scale
  5953.                         corner: updateRect corner + scale // scale * scale.
  5954.                 buffToDisplay copyQuad: updateRect innerCorners
  5955.                             toRect: (updateRect origin // scale + buffRect origin
  5956.                                         extent: updateRect extent // scale).
  5957.                 prevP _ p]]]! !
  5958.  
  5959. !BitBlt class methodsFor: 'examples'!
  5960. exampleOne
  5961.     "This tests BitBlt by displaying the result of all sixteen combination rules that BitBlt is capable of using. (Please see the comment in BitBlt for the meaning of the combination rules)."
  5962.     | path |
  5963.     path _ Path new.
  5964.     0 to: 3 do: [:i | 0 to: 3 do: [:j | path add: j * 100 @ (i * 75)]].
  5965.     Display fillWhite.
  5966.     path _ path translateBy: 60 @ 40.
  5967.     1 to: 16 do: [:index | BitBlt
  5968.             exampleAt: (path at: index)
  5969.             rule: index - 1
  5970.             fillColor: Color black]
  5971.  
  5972.     "BitBlt exampleOne"! !
  5973.  
  5974. !BitBlt class methodsFor: 'examples'!
  5975. exampleTwo
  5976.     "This is to test painting with a gray tone. It also tests that the seaming with gray patterns is correct in the microcode. Lets you paint for a while and then automatically stops."
  5977.     | f aBitBlt |
  5978.     "create a small black Form source as a brush. "
  5979.     f _ Form extent: 20 @ 20.
  5980.     f fillBlack.
  5981.     "create a BitBlt which will OR gray into the display. "
  5982.     aBitBlt _ BitBlt
  5983.         destForm: Display
  5984.         sourceForm: f
  5985.         fillColor: Color gray
  5986.         combinationRule: Form under
  5987.         destOrigin: Sensor cursorPoint
  5988.         sourceOrigin: 0 @ 0
  5989.         extent: f extent
  5990.         clipRect: Display computeBoundingBox.
  5991.     "paint the gray Form on the screen for a while. "
  5992.     [Sensor anyButtonPressed] whileFalse: 
  5993.         [aBitBlt destOrigin: Sensor cursorPoint.
  5994.         aBitBlt copyBits]
  5995.  
  5996.     "BitBlt exampleTwo"! !
  5997.  
  5998.  
  5999. !BitBlt class methodsFor: 'private'!
  6000. exampleAt: originPoint rule: rule fillColor: mask 
  6001.     "This builds a source and destination form and copies the source to the
  6002.     destination using the specifed rule and mask. It is called from the method
  6003.     named exampleOne."
  6004.  
  6005.     | s d border aBitBlt | 
  6006.     border_Form extent: 32@32.
  6007.     border fillBlack.
  6008.     border fill: (1@1 extent: 30@30) fillColor: Color white.
  6009.     s _ Form extent: 32@32.
  6010.     s fillWhite.
  6011.     s fillBlack: (7@7 corner: 25@25).
  6012.     d _ Form extent: 32@32.
  6013.     d fillWhite.
  6014.     d fillBlack: (0@0 corner: 32@16).
  6015.  
  6016.     s displayOn: Display at: originPoint.
  6017.     border displayOn: Display at: originPoint rule: Form under.
  6018.     d displayOn: Display at: originPoint + (s width @0).
  6019.     border displayOn: Display at: originPoint + (s width @0) rule: Form under.
  6020.  
  6021.     d displayOn: Display at: originPoint + (s extent // (2 @ 1)).
  6022.     aBitBlt _ BitBlt
  6023.         destForm: Display
  6024.         sourceForm: s
  6025.         fillColor: mask
  6026.         combinationRule: rule
  6027.         destOrigin: originPoint + (s extent // (2 @ 1))
  6028.         sourceOrigin: 0 @ 0
  6029.         extent: s extent
  6030.         clipRect: Display computeBoundingBox.
  6031.     aBitBlt copyBits.
  6032.     border 
  6033.         displayOn: Display at: originPoint + (s extent // (2 @ 1))
  6034.         rule: Form under.
  6035.    
  6036.     "BitBlt exampleAt: 100@100 rule: Form over fillColor: Display gray"! !
  6037. Object subclass: #BitBltSimulation
  6038.     instanceVariableNames: 'destForm sourceForm halftoneForm combinationRule destX destY width height sourceX sourceY clipX clipY clipWidth clipHeight sourceBits sourceRaster sourcePixSize destBits destRaster destPixSize pixPerWord bitCount skew mask1 mask2 preload nWords hDir vDir sourceIndex sourceDelta destIndex destDelta sx sy dx dy bbW bbH srcWidth srcHeight halftoneHeight noSource noHalftone halftoneBase colorMap cmBitsPerColor srcBitIndex scanStart scanStop scanString scanRightX scanStopArray scanDisplayFlag scanXTable stopCode bitBltOop affectedL affectedR affectedT affectedB interpreterProxy opTable '
  6039.     classVariableNames: 'AllOnes BBClipHeightIndex BBClipWidthIndex BBClipXIndex BBClipYIndex BBColorMapIndex BBDestFormIndex BBDestXIndex BBDestYIndex BBHalftoneFormIndex BBHeightIndex BBLastIndex BBRuleIndex BBSourceFormIndex BBSourceXIndex BBSourceYIndex BBWarpBase BBWidthIndex BBXTableIndex BinaryPoint CrossedX EndOfRun FixedPt1 FormBitsIndex FormDepthIndex FormHeightIndex FormWidthIndex OpTable OpTableSize '
  6040.     poolDictionaries: ''
  6041.     category: 'Squeak-Interpreter'!
  6042. !BitBltSimulation commentStamp: 'di 5/22/1998 16:32' prior: 0!
  6043. BitBltSimulation comment:
  6044. 'This class implements BitBlt, much as specified in the Blue Book spec.
  6045.  
  6046. Performance has been enhanced through the use of pointer variables such as sourceIndex and destIndex, and by separating several special cases of the inner loop.
  6047.  
  6048. Operation has been extended to color, with support for 1, 2, 4, 8, 16, and 32-bit pixel sizes.  Conversion between different pixel sizes is facilitated by accepting an optional color map.
  6049.  
  6050. In addition to the original 16 combination rules, this BitBlt supports
  6051.     16    fail (to simulate paint)
  6052.     17    fail (to simulate mask)
  6053.     18    sourceWord + destinationWord
  6054.     19    sourceWord - destinationWord
  6055.     20    rgbAdd: sourceWord with: destinationWord
  6056.     21    rgbSub: sourceWord with: destinationWord
  6057.     22    rgbDiff: sourceWord with: destinationWord
  6058.     23    tallyIntoMap: destinationWord
  6059.     24    alphaBlend: sourceWord with: destinationWord
  6060.     25    pixPaint: sourceWord with: destinationWord
  6061.     26    pixMask: sourceWord with: destinationWord
  6062.     27    rgbMax: sourceWord with: destinationWord
  6063.     28    rgbMin: sourceWord with: destinationWord
  6064.     29    rgbMin: sourceWord bitInvert32 with: destinationWord
  6065.  
  6066. This implementation has also been fitted with an experimental "warp drive" that allows abritrary scaling and rotation (and even limited affine deformations) with all BitBlt storage modes supported.
  6067. '!
  6068.  
  6069.  
  6070. !BitBltSimulation methodsFor: 'interpreter interface'!
  6071. drawLoopX: xDelta Y: yDelta 
  6072.     "This is the primitive implementation of the line-drawing loop.
  6073.     See the comments in BitBlt>>drawLoopX:Y:"
  6074.     | dx1 dy1 px py P affL affR affT affB |
  6075.     xDelta > 0
  6076.         ifTrue: [dx1 _ 1]
  6077.         ifFalse: [xDelta = 0
  6078.                 ifTrue: [dx1 _ 0]
  6079.                 ifFalse: [dx1 _ -1]].
  6080.     yDelta > 0
  6081.         ifTrue: [dy1 _ 1]
  6082.         ifFalse: [yDelta = 0
  6083.                 ifTrue: [dy1 _ 0]
  6084.                 ifFalse: [dy1 _ -1]].
  6085.     px _ yDelta abs.
  6086.     py _ xDelta abs.
  6087.     affL _ affT _ 9999.  "init null rectangle"
  6088.     affR _ affB _ -9999.
  6089.     py > px
  6090.         ifTrue: 
  6091.             ["more horizontal"
  6092.             P _ py // 2.
  6093.             1 to: py do: 
  6094.                 [:i |
  6095.                 destX _ destX + dx1.
  6096.                 (P _ P - px) < 0 ifTrue: 
  6097.                     [destY _ destY + dy1.
  6098.                     P _ P + py].
  6099.                 i < py ifTrue:
  6100.                     [self copyBits.
  6101.                     (affectedL < affectedR and: [affectedT < affectedB]) ifTrue:
  6102.                         ["Affected rectangle grows along the line"
  6103.                         affL _ affL min: affectedL.
  6104.                         affR _ affR max: affectedR.
  6105.                         affT _ affT min: affectedT.
  6106.                         affB _ affB max: affectedB.
  6107.                         (affR - affL) * (affB - affT) > 4000 ifTrue:
  6108.                             ["If affected rectangle gets large, update it in chunks"
  6109.                             affectedL _ affL.  affectedR _ affR.
  6110.                             affectedT _ affT.  affectedB _ affB.
  6111.                             interpreterProxy showDisplayBits.
  6112.                             affL _ affT _ 9999.  "init null rectangle"
  6113.                             affR _ affB _ -9999]].
  6114.                     ]]]
  6115.         ifFalse: 
  6116.             ["more vertical"
  6117.             P _ px // 2.
  6118.             1 to: px do:
  6119.                 [:i |
  6120.                 destY _ destY + dy1.
  6121.                 (P _ P - py) < 0 ifTrue: 
  6122.                     [destX _ destX + dx1.
  6123.                     P _ P + px].
  6124.                 i < px ifTrue:
  6125.                     [self copyBits.
  6126.                     (affectedL < affectedR and: [affectedT < affectedB]) ifTrue:
  6127.                         ["Affected rectangle grows along the line"
  6128.                         affL _ affL min: affectedL.
  6129.                         affR _ affR max: affectedR.
  6130.                         affT _ affT min: affectedT.
  6131.                         affB _ affB max: affectedB.
  6132.                         (affR - affL) * (affB - affT) > 4000 ifTrue:
  6133.                             ["If affected rectangle gets large, update it in chunks"
  6134.                             affectedL _ affL.  affectedR _ affR.
  6135.                             affectedT _ affT.  affectedB _ affB.
  6136.                             interpreterProxy showDisplayBits.
  6137.                             affL _ affT _ 9999.  "init null rectangle"
  6138.                             affR _ affB _ -9999]].
  6139.                     ]]].
  6140.  
  6141.     "Remaining affected rect"
  6142.     affectedL _ affL.  affectedR _ affR.
  6143.     affectedT _ affT.  affectedB _ affB.
  6144.  
  6145.     "store destX, Y back"    
  6146.     interpreterProxy storeInteger: BBDestXIndex ofObject: bitBltOop withValue: destX.
  6147.     interpreterProxy storeInteger: BBDestYIndex ofObject: bitBltOop withValue: destY.! !
  6148.  
  6149. !BitBltSimulation methodsFor: 'interpreter interface'!
  6150. loadBitBltFrom: bbObj
  6151.     "Load context from BitBlt instance.  Return false if anything is amiss"
  6152.     "NOTE this should all be changed to minX/maxX coordinates for simpler clipping
  6153.         -- once it works!!"
  6154.     | destBitsSize destWidth destHeight sourceBitsSize sourcePixPerWord cmSize halftoneBits |
  6155.     bitBltOop _ bbObj.
  6156.     combinationRule _ interpreterProxy fetchInteger: BBRuleIndex ofObject: bitBltOop.
  6157.     (interpreterProxy failed
  6158.         or: [combinationRule < 0 or: [combinationRule > 29]])
  6159.          ifTrue: [^ false  "operation out of range"].
  6160.     (combinationRule >= 16 and: [combinationRule <= 17])
  6161.          ifTrue: [^ false  "fail for old simulated paint, erase modes"].
  6162.     sourceForm _ interpreterProxy fetchPointer: BBSourceFormIndex ofObject: bitBltOop.
  6163.     noSource _ self ignoreSourceOrHalftone: sourceForm.
  6164.     halftoneForm _ interpreterProxy fetchPointer: BBHalftoneFormIndex ofObject: bitBltOop.
  6165.     noHalftone _ self ignoreSourceOrHalftone: halftoneForm.
  6166.  
  6167.     destForm _ interpreterProxy fetchPointer: BBDestFormIndex ofObject: bitBltOop.
  6168.         ((interpreterProxy isPointers: destForm) and: [(interpreterProxy lengthOf: destForm) >= 4])
  6169.             ifFalse: [^ false].
  6170.         destBits _ interpreterProxy fetchPointer: FormBitsIndex ofObject: destForm.
  6171.         destBitsSize _ interpreterProxy byteLengthOf: destBits.
  6172.         destWidth _ interpreterProxy fetchInteger: FormWidthIndex ofObject: destForm.
  6173.         destHeight _ interpreterProxy fetchInteger: FormHeightIndex ofObject: destForm.
  6174.         (destWidth >= 0 and: [destHeight >= 0])
  6175.             ifFalse: [^ false].
  6176.         destPixSize _ interpreterProxy fetchInteger: FormDepthIndex ofObject: destForm.
  6177.         pixPerWord _ 32 // destPixSize.
  6178.         destRaster _ destWidth + (pixPerWord-1) // pixPerWord.
  6179.         ((interpreterProxy isWordsOrBytes: destBits)
  6180.             and: [destBitsSize = (destRaster * destHeight * 4)])
  6181.             ifFalse: [^ false].    
  6182.     destX _ interpreterProxy fetchIntegerOrTruncFloat: BBDestXIndex ofObject: bitBltOop.
  6183.     destY _ interpreterProxy fetchIntegerOrTruncFloat: BBDestYIndex ofObject: bitBltOop.
  6184.     width _ interpreterProxy fetchIntegerOrTruncFloat: BBWidthIndex ofObject: bitBltOop.
  6185.     height _ interpreterProxy fetchIntegerOrTruncFloat: BBHeightIndex ofObject: bitBltOop.
  6186.         interpreterProxy failed ifTrue: [^ false  "non-integer value"].
  6187.  
  6188.     noSource ifTrue:
  6189.         [sourceX _ sourceY _ 0]
  6190.         ifFalse: 
  6191.         [((interpreterProxy isPointers: sourceForm) and: [(interpreterProxy lengthOf: sourceForm) >= 4])
  6192.             ifFalse: [^ false].
  6193.         sourceBits _ interpreterProxy fetchPointer: FormBitsIndex ofObject: sourceForm.
  6194.         sourceBitsSize _ interpreterProxy byteLengthOf: sourceBits.
  6195.         srcWidth _ interpreterProxy fetchIntegerOrTruncFloat: FormWidthIndex ofObject: sourceForm.
  6196.         srcHeight _ interpreterProxy fetchIntegerOrTruncFloat: FormHeightIndex ofObject: sourceForm.
  6197.         (srcWidth >= 0 and: [srcHeight >= 0])
  6198.             ifFalse: [^ false].
  6199.         sourcePixSize _ interpreterProxy fetchInteger: FormDepthIndex ofObject: sourceForm.
  6200.         sourcePixPerWord _ 32 // sourcePixSize.
  6201.         sourceRaster _ srcWidth + (sourcePixPerWord-1) // sourcePixPerWord.
  6202.         ((interpreterProxy isWordsOrBytes: sourceBits)
  6203.             and: [sourceBitsSize = (sourceRaster * srcHeight * 4)])
  6204.             ifFalse: [^ false].
  6205.         colorMap _ interpreterProxy fetchPointer: BBColorMapIndex ofObject: bitBltOop.
  6206.         "ColorMap, if not nil, must be longWords, and 
  6207.         2^N long, where N = sourcePixSize for 1, 2, 4, 8 bits, 
  6208.         or N = 9, 12, or 15 (3, 4, 5 bits per color) for 16 or 32 bits."
  6209.         colorMap = interpreterProxy nilObject ifFalse:
  6210.             [(interpreterProxy isWords: colorMap)
  6211.             ifTrue:
  6212.             [cmSize _ interpreterProxy lengthOf: colorMap.
  6213.             cmBitsPerColor _ 0.
  6214.             cmSize = 512 ifTrue: [cmBitsPerColor _ 3].
  6215.             cmSize = 4096 ifTrue: [cmBitsPerColor _ 4].
  6216.             cmSize = 32768 ifTrue: [cmBitsPerColor _ 5].
  6217.             interpreterProxy primIndex ~= 147 ifTrue:
  6218.                 ["WarpBlt has different checks on the color map"
  6219.                 sourcePixSize <= 8
  6220.                 ifTrue: [cmSize = (1 << sourcePixSize) ifFalse: [^ false] ]
  6221.                 ifFalse: [cmBitsPerColor = 0 ifTrue: [^ false] ]]
  6222.             ]
  6223.             ifFalse: [^ false]].
  6224.         sourceX _ interpreterProxy fetchIntegerOrTruncFloat: BBSourceXIndex ofObject: bitBltOop.
  6225.         sourceY _ interpreterProxy fetchIntegerOrTruncFloat: BBSourceYIndex ofObject: bitBltOop].
  6226.  
  6227.     noHalftone ifFalse: 
  6228.         [((interpreterProxy isPointers: halftoneForm) and: [(interpreterProxy lengthOf: halftoneForm) >= 4])
  6229.         ifTrue:
  6230.         ["Old-style 32xN monochrome halftone Forms"
  6231.         halftoneBits _ interpreterProxy fetchPointer: FormBitsIndex ofObject: halftoneForm.
  6232.         halftoneHeight _ interpreterProxy fetchInteger: FormHeightIndex ofObject: halftoneForm.
  6233.         (interpreterProxy isWords: halftoneBits)
  6234.             ifFalse: [noHalftone _ true]]
  6235.         ifFalse:
  6236.         ["New spec accepts, basically, a word array"
  6237.         ((interpreterProxy isPointers: halftoneForm) not
  6238.             and: [interpreterProxy isWords: halftoneForm])
  6239.             ifFalse: [^ false].
  6240.         halftoneBits _ halftoneForm.
  6241.         halftoneHeight _ interpreterProxy lengthOf: halftoneBits].
  6242.     halftoneBase _ halftoneBits + 4].
  6243.  
  6244.     clipX _ interpreterProxy fetchIntegerOrTruncFloat: BBClipXIndex ofObject: bitBltOop.
  6245.     clipY _ interpreterProxy fetchIntegerOrTruncFloat: BBClipYIndex ofObject: bitBltOop.
  6246.     clipWidth _ interpreterProxy fetchIntegerOrTruncFloat: BBClipWidthIndex ofObject: bitBltOop.
  6247.     clipHeight _ interpreterProxy fetchIntegerOrTruncFloat: BBClipHeightIndex ofObject: bitBltOop.
  6248.         interpreterProxy failed ifTrue: [^ false  "non-integer value"].
  6249.     clipX < 0 ifTrue: [clipWidth _ clipWidth + clipX.  clipX _ 0].
  6250.     clipY < 0 ifTrue: [clipHeight _ clipHeight + clipY.  clipY _ 0].
  6251.     clipX+clipWidth > destWidth ifTrue: [clipWidth _ destWidth - clipX].
  6252.     clipY+clipHeight > destHeight ifTrue: [clipHeight _ destHeight - clipY].
  6253.  
  6254.     ^ true! !
  6255.  
  6256. !BitBltSimulation methodsFor: 'interpreter interface'!
  6257. loadScannerFrom: bbObj
  6258.     start: start stop: stop string: string rightX: rightX
  6259.     stopArray: stopArray displayFlag: displayFlag
  6260.  
  6261.     self inline: false.
  6262.     "Load arguments and Scanner state"
  6263.     scanStart _ start.
  6264.     scanStop _ stop.
  6265.     scanString _ string.
  6266.     scanRightX _ rightX.
  6267.     scanStopArray _ stopArray.
  6268.     scanDisplayFlag _ displayFlag.
  6269.     interpreterProxy success: (
  6270.         (interpreterProxy isPointers: scanStopArray)
  6271.             and: [(interpreterProxy lengthOf: scanStopArray) >= 1]).
  6272.     scanXTable _ interpreterProxy fetchPointer: BBXTableIndex ofObject: bbObj.
  6273.     interpreterProxy success: (
  6274.         (interpreterProxy isPointers: scanXTable)
  6275.             and: [(interpreterProxy lengthOf: scanXTable) >= 1]).
  6276.  
  6277.     "width and sourceX may not be set..."
  6278.     interpreterProxy storeInteger: BBWidthIndex ofObject: bbObj withValue: 0.
  6279.     interpreterProxy storeInteger: BBSourceXIndex ofObject: bbObj withValue: 0.
  6280.  
  6281.     "Now load BitBlt state if displaying"
  6282.     scanDisplayFlag
  6283.         ifTrue: [interpreterProxy success: (self loadBitBltFrom: bbObj)]
  6284.         ifFalse: [bitBltOop _ bbObj.
  6285.                 destX _ interpreterProxy fetchIntegerOrTruncFloat: BBDestXIndex ofObject: bbObj].
  6286.     ^interpreterProxy failed not! !
  6287.  
  6288. !BitBltSimulation methodsFor: 'interpreter interface'!
  6289. scanCharacters
  6290.  
  6291.     | left top lastIndex charVal ascii sourceX2 nextDestX |
  6292.     scanDisplayFlag ifTrue:
  6293.         [self clipRange.  "Need to get true x, y for affectedRectangle"
  6294.         left _ dx.
  6295.         top _ dy].
  6296.     lastIndex _ scanStart.
  6297.     [lastIndex <= scanStop]
  6298.         whileTrue: [
  6299.             charVal _ interpreterProxy stObject: scanString at: lastIndex.
  6300.             ascii _ interpreterProxy integerValueOf: charVal.
  6301.             interpreterProxy failed ifTrue: [^ nil].
  6302.             stopCode _ interpreterProxy stObject: scanStopArray at: ascii + 1.
  6303.             interpreterProxy failed ifTrue: [^ nil].
  6304.             stopCode = interpreterProxy nilObject
  6305.                 ifFalse: [^ self returnAt: ascii + 1
  6306.                              lastIndex: lastIndex
  6307.                                   left: left
  6308.                                   top: top].
  6309.             sourceX _ interpreterProxy stObject: scanXTable at: ascii + 1.
  6310.             sourceX2 _ interpreterProxy stObject: scanXTable at: ascii + 2.
  6311.             interpreterProxy failed ifTrue: [^ nil].
  6312.             (interpreterProxy isIntegerObject: sourceX) & (interpreterProxy isIntegerObject: sourceX2)
  6313.                 ifTrue: [sourceX _ interpreterProxy integerValueOf: sourceX.
  6314.                         sourceX2 _ interpreterProxy integerValueOf: sourceX2]
  6315.                 ifFalse: [interpreterProxy primitiveFail. ^ nil].
  6316.             nextDestX _ destX + (width _ sourceX2 - sourceX).
  6317.             nextDestX > scanRightX
  6318.                 ifTrue: [^ self returnAt: CrossedX
  6319.                              lastIndex: lastIndex
  6320.                                   left: left
  6321.                                   top: top].
  6322.             scanDisplayFlag ifTrue: [self copyBits].
  6323.             destX _ nextDestX.
  6324.             interpreterProxy storeInteger: BBDestXIndex ofObject: bitBltOop withValue: destX.
  6325.             lastIndex _ lastIndex + 1].
  6326.     self returnAt: EndOfRun
  6327.          lastIndex: scanStop
  6328.               left: left
  6329.               top: top! !
  6330.  
  6331. !BitBltSimulation methodsFor: 'interpreter interface'!
  6332. setInterpreter: anInterpreter
  6333.     "Interface for InterpreterSimulator. Allows BitBltSimulation object to send messages to the interpreter. The translator will replace sends to 'interpreterProxy' with sends to self, as if BitBltSimulation were part of the interpreter."
  6334.  
  6335.     interpreterProxy _ anInterpreter.! !
  6336.  
  6337.  
  6338. !BitBltSimulation methodsFor: 'accessing'!
  6339. affectedBottom
  6340.  
  6341.     ^affectedB! !
  6342.  
  6343. !BitBltSimulation methodsFor: 'accessing'!
  6344. affectedLeft
  6345.  
  6346.     ^affectedL! !
  6347.  
  6348. !BitBltSimulation methodsFor: 'accessing'!
  6349. affectedRight
  6350.  
  6351.     ^affectedR! !
  6352.  
  6353. !BitBltSimulation methodsFor: 'accessing'!
  6354. affectedTop
  6355.  
  6356.     ^affectedT! !
  6357.  
  6358. !BitBltSimulation methodsFor: 'accessing'!
  6359. stopReason
  6360.  
  6361.     ^stopCode! !
  6362.  
  6363. !BitBltSimulation methodsFor: 'accessing'!
  6364. targetForm
  6365.     "Return the destination form of a copyBits or scanCharacters operation."
  6366.  
  6367.     ^destForm! !
  6368.  
  6369.  
  6370. !BitBltSimulation methodsFor: 'setup'!
  6371. checkSourceOverlap
  6372.     | t |
  6373.     "check for possible overlap of source and destination"
  6374.     (sourceForm = destForm and: [dy >= sy]) ifTrue:
  6375.         [dy > sy ifTrue:
  6376.             ["have to start at bottom"
  6377.             vDir _ -1.
  6378.             sy _ sy + bbH - 1.
  6379.             dy _ dy + bbH - 1]
  6380.         ifFalse:
  6381.             [dx > sx ifTrue:
  6382.                 ["y's are equal, but x's are backward"
  6383.                 hDir _ -1.
  6384.                 sx _ sx + bbW - 1.
  6385.                 "start at right"
  6386.                 dx _ dx + bbW - 1.
  6387.                 "and fix up masks"
  6388.                 nWords > 1 ifTrue: 
  6389.                     [t _ mask1.
  6390.                     mask1 _ mask2.
  6391.                     mask2 _ t]]].
  6392.         "Dest inits may be affected by this change"
  6393.         destIndex _ (destBits + 4) + (dy * destRaster + (dx // pixPerWord) *4).
  6394.         destDelta _ 4 * ((destRaster * vDir) - (nWords * hDir))]! !
  6395.  
  6396. !BitBltSimulation methodsFor: 'setup'!
  6397. clipRange
  6398.     "clip and adjust source origin and extent appropriately"
  6399.     "first in x"
  6400.     destX >= clipX
  6401.         ifTrue: [sx _ sourceX.
  6402.                 dx _ destX.
  6403.                 bbW _ width]
  6404.         ifFalse: [sx _ sourceX + (clipX - destX).
  6405.                 bbW _ width - (clipX - destX).
  6406.                 dx _ clipX].
  6407.     (dx + bbW) > (clipX + clipWidth)
  6408.         ifTrue: [bbW _ bbW - ((dx + bbW) - (clipX + clipWidth))].
  6409.     "then in y"
  6410.     destY >= clipY
  6411.         ifTrue: [sy _ sourceY.
  6412.                 dy _ destY.
  6413.                 bbH _ height]
  6414.         ifFalse: [sy _ sourceY + clipY - destY.
  6415.                 bbH _ height - (clipY - destY).
  6416.                 dy _ clipY].
  6417.     (dy + bbH) > (clipY + clipHeight)
  6418.         ifTrue: [bbH _ bbH - ((dy + bbH) - (clipY + clipHeight))].
  6419.     noSource ifTrue: [^ nil].
  6420.     sx < 0
  6421.         ifTrue: [dx _ dx - sx.
  6422.                 bbW _ bbW + sx.
  6423.                 sx _ 0].
  6424.     sx + bbW > srcWidth
  6425.         ifTrue: [bbW _ bbW - (sx + bbW - srcWidth)].
  6426.     sy < 0
  6427.         ifTrue: [dy _ dy - sy.
  6428.                 bbH _ bbH + sy.
  6429.                 sy _ 0].
  6430.     sy + bbH > srcHeight
  6431.         ifTrue: [bbH _ bbH - (sy + bbH - srcHeight)]! !
  6432.  
  6433. !BitBltSimulation methodsFor: 'setup'!
  6434. copyBits
  6435.     self clipRange.
  6436.     (bbW <= 0 or: [bbH <= 0]) ifTrue:
  6437.         ["zero width or height; noop"
  6438.         affectedL _ affectedR _ affectedT _ affectedB _ 0.
  6439.         ^ nil].
  6440.  
  6441.     self destMaskAndPointerInit.
  6442.     bitCount _ 0.
  6443.     noSource
  6444.         ifTrue: [self copyLoopNoSource]
  6445.         ifFalse: [self checkSourceOverlap.
  6446.                 (sourcePixSize ~= destPixSize
  6447.                     or: [colorMap ~= interpreterProxy nilObject])
  6448.                     ifTrue: [self copyLoopPixMap]
  6449.                     ifFalse: [self sourceSkewAndPointerInit.
  6450.                             self copyLoop]].
  6451.  
  6452.     combinationRule = 22 ifTrue:
  6453.         ["zero width and height; return the count"
  6454.         affectedL _ affectedR _ affectedT _ affectedB _ 0.
  6455.         interpreterProxy pop: 1.
  6456.         ^ interpreterProxy pushInteger: bitCount].
  6457.  
  6458.     hDir > 0
  6459.         ifTrue: [affectedL _ dx.
  6460.                 affectedR _ dx + bbW]
  6461.         ifFalse: [affectedL _ dx - bbW + 1.
  6462.                 affectedR _ dx + 1].
  6463.     vDir > 0
  6464.         ifTrue: [affectedT _ dy.
  6465.                 affectedB _ dy + bbH]
  6466.         ifFalse: [affectedT _ dy - bbH + 1.
  6467.                 affectedB _ dy + 1]! !
  6468.  
  6469. !BitBltSimulation methodsFor: 'setup'!
  6470. destMaskAndPointerInit
  6471.     "Compute masks for left and right destination words"
  6472.     | startBits pixPerM1 endBits |
  6473.     pixPerM1 _ pixPerWord - 1.  "A mask, assuming power of two"
  6474.     "how many pixels in first word"
  6475.     startBits _ pixPerWord - (dx bitAnd: pixPerM1).
  6476.     mask1 _ AllOnes >> (32 - (startBits*destPixSize)).
  6477.     "how many pixels in last word"
  6478.     endBits _ ((dx + bbW - 1) bitAnd: pixPerM1) + 1.
  6479.     mask2 _ AllOnes << (32 - (endBits*destPixSize)).
  6480.     "determine number of words stored per line; merge masks if only 1"
  6481.     bbW < startBits
  6482.         ifTrue: [mask1 _ mask1 bitAnd: mask2.
  6483.                 mask2 _ 0.
  6484.                 nWords _ 1]
  6485.         ifFalse: [nWords _ (bbW - startBits) + pixPerM1 // pixPerWord + 1].
  6486.     hDir _ vDir _ 1. "defaults for no overlap with source"
  6487.  
  6488.     "calculate byte addr and delta, based on first word of data"
  6489.     "Note raster and nwords are longs, not bytes"
  6490.     destIndex _ (destBits + 4) + (dy * destRaster + (dx // pixPerWord) *4).
  6491.     destDelta _ 4 * ((destRaster * vDir) - (nWords * hDir)).  "byte addr delta"! !
  6492.  
  6493. !BitBltSimulation methodsFor: 'setup'!
  6494. ignoreSourceOrHalftone: formPointer
  6495.  
  6496.     formPointer = interpreterProxy nilObject ifTrue: [ ^true ].
  6497.     combinationRule = 0 ifTrue: [ ^true ].
  6498.     combinationRule = 5 ifTrue: [ ^true ].
  6499.     combinationRule = 10 ifTrue: [ ^true ].
  6500.     combinationRule = 15 ifTrue: [ ^true ].
  6501.     ^false! !
  6502.  
  6503. !BitBltSimulation methodsFor: 'setup'!
  6504. returnAt: stopIndex lastIndex: lastIndex left: left top: top
  6505.  
  6506.     stopCode _ interpreterProxy stObject: scanStopArray at: stopIndex.
  6507.     interpreterProxy failed ifTrue: [^ nil].
  6508.     interpreterProxy storeInteger: BBLastIndex ofObject: bitBltOop withValue: lastIndex.
  6509.     scanDisplayFlag ifTrue: [
  6510.         "Now we know extent of affected rectangle"
  6511.         affectedL _ left.
  6512.         affectedR _ bbW + dx.
  6513.         affectedT _ top.
  6514.         affectedB _ bbH + dy.
  6515.     ].! !
  6516.  
  6517. !BitBltSimulation methodsFor: 'setup'!
  6518. sourceSkewAndPointerInit
  6519.     "This is only used when source and dest are same depth,
  6520.     ie, when the barrel-shift copy loop is used."
  6521.     | dWid sxLowBits dxLowBits pixPerM1 |
  6522.     pixPerM1 _ pixPerWord - 1.  "A mask, assuming power of two"
  6523.     sxLowBits _ sx bitAnd: pixPerM1.
  6524.     dxLowBits _ dx bitAnd: pixPerM1.
  6525.     "check if need to preload buffer
  6526.     (i.e., two words of source needed for first word of destination)"
  6527.     hDir > 0 ifTrue:
  6528.         ["n Bits stored in 1st word of dest"
  6529.         dWid _ bbW min: pixPerWord - dxLowBits.
  6530.         preload _ (sxLowBits + dWid) > pixPerM1]
  6531.     ifFalse:
  6532.         [dWid _ bbW min: dxLowBits + 1.
  6533.         preload _ (sxLowBits - dWid + 1) < 0].
  6534.  
  6535.     "calculate right-shift skew from source to dest"
  6536.     skew _ (sxLowBits - dxLowBits) * destPixSize.  " -32..32 "
  6537.     preload ifTrue: 
  6538.         [skew < 0
  6539.             ifTrue: [skew _ skew+32]
  6540.             ifFalse: [skew _ skew-32]].
  6541.  
  6542.     "Calc byte addr and delta from longWord info"
  6543.     sourceIndex _ (sourceBits + 4) + (sy * sourceRaster + (sx // (32//sourcePixSize)) *4).
  6544.     "calculate increments from end of 1 line to start of next"
  6545.     sourceDelta _ 4 * ((sourceRaster * vDir) - (nWords * hDir)).
  6546.     preload ifTrue:
  6547.         ["Compensate for extra source word fetched"
  6548.         sourceDelta _ sourceDelta - (4*hDir)].! !
  6549.  
  6550. !BitBltSimulation methodsFor: 'setup'!
  6551. warpBits
  6552.     | ns |
  6553.     ns _ noSource.  noSource _ true.
  6554.         self clipRange.  "noSource suppresses sourceRect clipping"
  6555.         noSource _ ns.
  6556.     (noSource or: [bbW <= 0 or: [bbH <= 0]]) ifTrue:
  6557.         ["zero width or height; noop"
  6558.         affectedL _ affectedR _ affectedT _ affectedB _ 0.
  6559.         ^ nil].
  6560.  
  6561.     self destMaskAndPointerInit.
  6562.     self warpLoop.
  6563.  
  6564.     hDir > 0
  6565.         ifTrue: [affectedL _ dx.
  6566.                 affectedR _ dx + bbW]
  6567.         ifFalse: [affectedL _ dx - bbW + 1.
  6568.                 affectedR _ dx + 1].
  6569.     vDir > 0
  6570.         ifTrue: [affectedT _ dy.
  6571.                 affectedB _ dy + bbH]
  6572.         ifFalse: [affectedT _ dy - bbH + 1.
  6573.                 affectedB _ dy + 1]! !
  6574.  
  6575.  
  6576. !BitBltSimulation methodsFor: 'inner loop' stamp: 'di 12/30/97 14:42'!
  6577. copyLoop
  6578.     | prevWord thisWord skewWord halftoneWord mergeWord hInc y unskew skewMask notSkewMask mergeFnwith |
  6579.     "This version of the inner loop assumes noSource = false."
  6580.     self inline: false.
  6581.     self var: #mergeFnwith declareC: 'int (*mergeFnwith)(int, int)'.
  6582.     mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'int (*)(int, int)'.
  6583.     mergeFnwith.  "null ref for compiler"
  6584.  
  6585.     hInc _ hDir*4.  "Byte delta"
  6586.     "degenerate skew fixed for Sparc. 10/20/96 ikp"
  6587.     skew == -32
  6588.         ifTrue: [skew _ unskew _ skewMask _ 0]
  6589.         ifFalse: [skew < 0
  6590.             ifTrue:
  6591.                 [unskew _ skew+32.
  6592.                 skewMask _ AllOnes << (0-skew)]
  6593.             ifFalse:
  6594.                 [skew == 0
  6595.                     ifTrue:
  6596.                         [unskew _ 0.
  6597.                         skewMask _ AllOnes]
  6598.                     ifFalse:
  6599.                         [unskew _ skew-32.
  6600.                         skewMask _ AllOnes >> skew]]].
  6601.     notSkewMask _ skewMask bitInvert32.
  6602.     noHalftone
  6603.         ifTrue: [halftoneWord _ AllOnes.  halftoneHeight _ 0]
  6604.         ifFalse: [halftoneWord _ interpreterProxy longAt: halftoneBase].
  6605.     y _ dy.
  6606.     1 to: bbH do: "here is the vertical loop"
  6607.         [ :i |
  6608.         halftoneHeight > 1 ifTrue:  "Otherwise, its always the same"
  6609.             [halftoneWord _ interpreterProxy longAt:
  6610.                         (halftoneBase + (y \\ halftoneHeight * 4)).
  6611.             y _ y + vDir].
  6612.         preload ifTrue:
  6613.             ["load the 64-bit shifter"
  6614.             prevWord _ interpreterProxy longAt: sourceIndex.
  6615.             sourceIndex _ sourceIndex + hInc]
  6616.             ifFalse:
  6617.             [prevWord _ 0].
  6618.  
  6619.     "Note: the horizontal loop has been expanded into three parts for speed:"
  6620.  
  6621.             "This first section requires masking of the destination store..."
  6622.             thisWord _ interpreterProxy longAt: sourceIndex.  "pick up next word"
  6623.             skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew)
  6624.                             bitOr:  "32-bit rotate"
  6625.                         ((thisWord bitAnd: skewMask) bitShift: skew).
  6626.             prevWord _ thisWord.
  6627.             sourceIndex _ sourceIndex + hInc.
  6628.             mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord)
  6629.                             with: (interpreterProxy longAt: destIndex).
  6630.             interpreterProxy longAt: destIndex
  6631.                 put: ((mask1 bitAnd: mergeWord)
  6632.                     bitOr: (mask1 bitInvert32 bitAnd: (interpreterProxy longAt: destIndex))).
  6633.             destIndex _ destIndex + hInc.
  6634.  
  6635.         "This central horizontal loop requires no store masking"
  6636. combinationRule = 3
  6637. ifTrue: [2 to: nWords-1 do: "Special inner loop for STORE"
  6638.             [ :word |
  6639.             thisWord _ interpreterProxy longAt: sourceIndex.  "pick up next word"
  6640.             skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew)
  6641.                             bitOr:  "32-bit rotate"
  6642.                         ((thisWord bitAnd: skewMask) bitShift: skew).
  6643.             prevWord _ thisWord.
  6644.             sourceIndex _ sourceIndex + hInc.
  6645.             interpreterProxy longAt: destIndex put: (skewWord bitAnd: halftoneWord).
  6646.             destIndex _ destIndex + hInc]
  6647. ] ifFalse: [2 to: nWords-1 do: "Normal inner loop does merge:"
  6648.             [ :word |
  6649.             thisWord _ interpreterProxy longAt: sourceIndex.  "pick up next word"
  6650.             skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew)
  6651.                             bitOr:  "32-bit rotate"
  6652.                         ((thisWord bitAnd: skewMask) bitShift: skew).
  6653.             prevWord _ thisWord.
  6654.             sourceIndex _ sourceIndex + hInc.
  6655.             mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord)
  6656.                             with: (interpreterProxy longAt: destIndex).
  6657.             interpreterProxy longAt: destIndex put: mergeWord.
  6658.             destIndex _ destIndex + hInc]
  6659. ].
  6660.  
  6661.         "This last section, if used, requires masking of the destination store..."
  6662.         nWords > 1 ifTrue:
  6663.             [thisWord _ interpreterProxy longAt: sourceIndex.  "pick up next word"
  6664.             skewWord _ ((prevWord bitAnd: notSkewMask) bitShift: unskew)
  6665.                             bitOr:  "32-bit rotate"
  6666.                         ((thisWord bitAnd: skewMask) bitShift: skew).
  6667.             prevWord _ thisWord.
  6668.             sourceIndex _ sourceIndex + hInc.
  6669.             mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord)
  6670.                             with: (interpreterProxy longAt: destIndex).
  6671.             interpreterProxy longAt: destIndex
  6672.                 put: ((mask2 bitAnd: mergeWord)
  6673.                     bitOr: (mask2 bitInvert32 bitAnd: (interpreterProxy longAt: destIndex))).
  6674.             destIndex _ destIndex + hInc].
  6675.  
  6676.     sourceIndex _ sourceIndex + sourceDelta.
  6677.     destIndex _ destIndex + destDelta]! !
  6678.  
  6679. !BitBltSimulation methodsFor: 'inner loop' stamp: 'di 12/30/97 14:43'!
  6680. copyLoopNoSource
  6681.     | halftoneWord mergeWord mergeFnwith |
  6682.     "Faster copyLoop when source not used.  hDir and vDir are both
  6683.     positive, and perload and skew are unused"
  6684.  
  6685.     self inline: false.
  6686.     self var: #mergeFnwith declareC: 'int (*mergeFnwith)(int, int)'.
  6687.     mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'int (*)(int, int)'.
  6688.     mergeFnwith.  "null ref for compiler"
  6689.  
  6690.     1 to: bbH do: "here is the vertical loop"
  6691.         [ :i |
  6692.         noHalftone
  6693.             ifTrue: [halftoneWord _ AllOnes]
  6694.             ifFalse: [halftoneWord _ interpreterProxy longAt: (halftoneBase + (dy+i-1 \\ halftoneHeight * 4))].
  6695.  
  6696.     "Note: the horizontal loop has been expanded into three parts for speed:"
  6697.  
  6698.             "This first section requires masking of the destination store..."
  6699.             mergeWord _ self mergeFn: halftoneWord
  6700.                             with: (interpreterProxy longAt: destIndex).
  6701.             interpreterProxy longAt: destIndex
  6702.                 put: ((mask1 bitAnd: mergeWord)
  6703.                     bitOr: (mask1 bitInvert32 bitAnd: (interpreterProxy longAt: destIndex))).
  6704.             destIndex _ destIndex + 4.
  6705.  
  6706.         "This central horizontal loop requires no store masking"
  6707. combinationRule = 3
  6708. ifTrue: [2 to: nWords-1 do: "Special inner loop for STORE"
  6709.             [ :word |
  6710.             interpreterProxy longAt: destIndex put: halftoneWord.
  6711.             destIndex _ destIndex + 4].
  6712. ] ifFalse: [2 to: nWords-1 do: "Normal inner loop does merge"
  6713.             [ :word |
  6714.             mergeWord _ self mergeFn: halftoneWord
  6715.                             with: (interpreterProxy longAt: destIndex).
  6716.             interpreterProxy longAt: destIndex put: mergeWord.
  6717.             destIndex _ destIndex + 4].
  6718.  
  6719. ].
  6720.  
  6721.         "This last section, if used, requires masking of the destination store..."
  6722.         nWords > 1 ifTrue:
  6723.             [mergeWord _ self mergeFn: halftoneWord
  6724.                             with: (interpreterProxy longAt: destIndex).
  6725.             interpreterProxy longAt: destIndex
  6726.                 put: ((mask2 bitAnd: mergeWord)
  6727.                     bitOr: (mask2 bitInvert32 bitAnd: (interpreterProxy longAt: destIndex))).
  6728.             destIndex _ destIndex + 4].
  6729.  
  6730.     destIndex _ destIndex + destDelta]! !
  6731.  
  6732. !BitBltSimulation methodsFor: 'inner loop' stamp: 'di 12/30/97 14:45'!
  6733. copyLoopPixMap
  6734.     "This version of the inner loop maps source pixels
  6735.     to a destination form with different depth.  Because it is already
  6736.     unweildy, the loop is not unrolled as in the other versions.
  6737.     Preload, skew and skewMask are all overlooked, since pickSourcePixels
  6738.     delivers its destination word already properly aligned.
  6739.     Note that pickSourcePixels could be copied in-line at the top of
  6740.     the horizontal loop, and some of its inits moved out of the loop."
  6741.  
  6742.     | skewWord halftoneWord mergeWord destMask srcPixPerWord scrStartBits nSourceIncs startBits endBits sourcePixMask destPixMask nullMap mergeFnwith |
  6743.  
  6744.     self inline: false.
  6745.     self var: #mergeFnwith declareC: 'int (*mergeFnwith)(int, int)'.
  6746.     mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'int (*)(int, int)'.
  6747.     mergeFnwith.  "null ref for compiler"
  6748.  
  6749.     "Additional inits peculiar to unequal source and dest pix size..."
  6750.     srcPixPerWord _ 32//sourcePixSize.
  6751.     "Check for degenerate shift values 4/28/97 ar"
  6752.     sourcePixSize = 32 
  6753.         ifTrue: [ sourcePixMask _ -1]
  6754.         ifFalse: [ sourcePixMask _ (1 << sourcePixSize) - 1].
  6755.     destPixSize = 32
  6756.         ifTrue: [ destPixMask _ -1]
  6757.         ifFalse: [ destPixMask _ (1 << destPixSize) - 1].
  6758.     nullMap _ colorMap = interpreterProxy nilObject.
  6759.     sourceIndex _ (sourceBits + 4) +
  6760.                     (sy * sourceRaster + (sx // srcPixPerWord) *4).
  6761.     scrStartBits _ srcPixPerWord - (sx bitAnd: srcPixPerWord-1).
  6762.     bbW < scrStartBits
  6763.         ifTrue: [nSourceIncs _ 0]
  6764.         ifFalse: [nSourceIncs _ (bbW - scrStartBits)//srcPixPerWord + 1].
  6765.     sourceDelta _ (sourceRaster - nSourceIncs) * 4.
  6766.  
  6767.     "Note following two items were already calculated in destmask setup!!"
  6768.     startBits _ pixPerWord - (dx bitAnd: pixPerWord-1).
  6769.     endBits _ ((dx + bbW - 1) bitAnd: pixPerWord-1) + 1.
  6770.  
  6771.     1 to: bbH do: "here is the vertical loop"
  6772.         [ :i |
  6773.         noHalftone
  6774.             ifTrue: [halftoneWord _ AllOnes]
  6775.             ifFalse: [halftoneWord _ interpreterProxy longAt: (halftoneBase + (dy+i-1 \\ halftoneHeight * 4))].
  6776.         srcBitIndex _ (sx bitAnd: srcPixPerWord - 1)*sourcePixSize.
  6777.         destMask _ mask1.
  6778.         "pick up first word"
  6779.         bbW < startBits
  6780.             ifTrue: [skewWord _ self pickSourcePixels: bbW nullMap: nullMap
  6781.                                     srcMask: sourcePixMask destMask: destPixMask.
  6782.                     skewWord _ skewWord   "See note below"
  6783.                             bitShift: (startBits - bbW)*destPixSize]
  6784.             ifFalse: [skewWord _ self pickSourcePixels: startBits nullMap: nullMap
  6785.                                     srcMask: sourcePixMask destMask: destPixMask]. 
  6786.  
  6787.         "Here is the horizontal loop..."
  6788.         1 to: nWords do: "here is the inner horizontal loop"
  6789.             [ :word |
  6790.             mergeWord _ self mergeFn: (skewWord bitAnd: halftoneWord)
  6791.                             with: ((interpreterProxy longAt: destIndex) bitAnd: destMask).
  6792.             interpreterProxy longAt: destIndex
  6793.                 put: ((destMask bitAnd: mergeWord)
  6794.                     bitOr:
  6795.                     (destMask bitInvert32 bitAnd: (interpreterProxy longAt: destIndex))).
  6796.             destIndex _ destIndex + 4.
  6797.             word >= (nWords - 1) ifTrue:
  6798.                 [word = nWords ifFalse:
  6799.                     ["set mask for last word in this row"
  6800.                     destMask _ mask2.
  6801.                     skewWord _ self pickSourcePixels: endBits nullMap: nullMap
  6802.                                     srcMask: sourcePixMask destMask: destPixMask.
  6803.                     skewWord _ skewWord   "See note below"
  6804.                             bitShift: (pixPerWord-endBits)*destPixSize]]
  6805.                 ifFalse: 
  6806.                 ["use fullword mask for inner loop"
  6807.                 destMask _ AllOnes.
  6808.                 skewWord _ self pickSourcePixels: pixPerWord nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask]].
  6809.  
  6810.     sourceIndex _ sourceIndex + sourceDelta.
  6811.     destIndex _ destIndex + destDelta]
  6812.  
  6813. "NOTE: in both noted shifts above, we are shifting the right-justified
  6814.  output of pickSourcePixels so that it is aligned with the destination word.
  6815.   Since it gets masked anyway, we could have just picked more pixels
  6816.  (startBits in the first case and destPixSize in the second), and it would
  6817.  have been simpler, but it is slower to run the pickSourcePixels loop. 
  6818.  CopyLoopAlphaHack takes advantage of this to avoid having to shift
  6819.  full-words in its alphaSource buffer" ! !
  6820.  
  6821. !BitBltSimulation methodsFor: 'inner loop'!
  6822. warpLoop
  6823.     | skewWord halftoneWord mergeWord destMask startBits
  6824.       deltaP12x deltaP12y deltaP43x deltaP43y pAx pAy
  6825.       xDelta yDelta pBx pBy smoothingCount sourceMapOop nSteps t |
  6826.  
  6827.     "This version of the inner loop traverses an arbirary quadrilateral
  6828.     source, thus producing a general affine transformation."
  6829.  
  6830.     (interpreterProxy fetchWordLengthOf: bitBltOop) >= (BBWarpBase+12)
  6831.         ifFalse: [^ interpreterProxy primitiveFail].
  6832.     nSteps _ height-1.  nSteps <= 0 ifTrue: [nSteps _ 1].
  6833.  
  6834.     pAx _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase ofObject: bitBltOop.
  6835.     t _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase+3 ofObject: bitBltOop.
  6836.     deltaP12x _ self deltaFrom: pAx to: t nSteps: nSteps.
  6837.     deltaP12x < 0 ifTrue: [pAx _ t - (nSteps*deltaP12x)].
  6838.  
  6839.     pAy _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase+1 ofObject: bitBltOop.
  6840.     t _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase+4 ofObject: bitBltOop.
  6841.     deltaP12y _ self deltaFrom: pAy to: t nSteps: nSteps.
  6842.     deltaP12y < 0 ifTrue: [pAy _ t - (nSteps*deltaP12y)].
  6843.  
  6844.     pBx _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase+9 ofObject: bitBltOop.
  6845.     t _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase+6 ofObject: bitBltOop.
  6846.     deltaP43x _ self deltaFrom: pBx to: t nSteps: nSteps.
  6847.     deltaP43x < 0 ifTrue: [pBx _ t - (nSteps*deltaP43x)].
  6848.  
  6849.     pBy _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase+10 ofObject: bitBltOop.
  6850.     t _ interpreterProxy fetchIntegerOrTruncFloat: BBWarpBase+7 ofObject: bitBltOop.
  6851.     deltaP43y _ self deltaFrom: pBy to: t nSteps: nSteps.
  6852.     deltaP43y < 0 ifTrue: [pBy _ t - (nSteps*deltaP43y)].
  6853.  
  6854.     interpreterProxy failed ifTrue: [^ false].  "ie if non-integers above"
  6855.     interpreterProxy argCount = 2
  6856.         ifTrue: [smoothingCount _ interpreterProxy stackIntegerValue: 1.
  6857.                 sourceMapOop _ interpreterProxy stackValue: 0.
  6858.                 sourceMapOop = interpreterProxy nilObject
  6859.                 ifTrue: [sourcePixSize < 16 ifTrue:
  6860.                     ["color map is required to smooth non-RGB dest"
  6861.                     ^ interpreterProxy primitiveFail]]
  6862.                 ifFalse: [(interpreterProxy fetchWordLengthOf: sourceMapOop)
  6863.                             < (1 << sourcePixSize) ifTrue:
  6864.                     ["sourceMap must be long enough for sourcePixSize"
  6865.                     ^ interpreterProxy primitiveFail]]]
  6866.         ifFalse: [smoothingCount _ 1.
  6867.                 sourceMapOop _ interpreterProxy nilObject].
  6868.     startBits _ pixPerWord - (dx bitAnd: pixPerWord-1).
  6869.     nSteps _ width-1.  nSteps <= 0 ifTrue: [nSteps _ 1].
  6870.  
  6871.     destY to: clipY-1 do:
  6872.         [ :i |    "Advance increments if there was clipping in y"
  6873.         pAx _ pAx + deltaP12x.
  6874.         pAy _ pAy + deltaP12y.
  6875.         pBx _ pBx + deltaP43x.
  6876.         pBy _ pBy + deltaP43y].
  6877.  
  6878.     1 to: bbH do:
  6879.         [ :i |        "here is the vertical loop..."
  6880.         xDelta _ self deltaFrom: pAx to: pBx nSteps: nSteps.
  6881.          xDelta >= 0 ifTrue: [sx _ pAx] ifFalse: [sx _ pBx - (nSteps*xDelta)].
  6882.         yDelta _ self deltaFrom: pAy to: pBy nSteps: nSteps.
  6883.          yDelta >= 0 ifTrue: [sy _ pAy] ifFalse: [sy _ pBy - (nSteps*yDelta)].
  6884.  
  6885.         destX to: clipX-1 do:
  6886.             [:word |    "Advance increments if there was clipping in x"
  6887.             sx _ sx + xDelta.
  6888.             sy _ sy + yDelta].
  6889.  
  6890.         noHalftone
  6891.             ifTrue: [halftoneWord _ AllOnes]
  6892.             ifFalse: [halftoneWord _ interpreterProxy longAt: (halftoneBase + (dy+i-1 \\ halftoneHeight * 4))].
  6893.         destMask _ mask1.
  6894.         "pick up first word"
  6895.         bbW < startBits
  6896.             ifTrue: [skewWord _ self warpSourcePixels: bbW
  6897.                                     xDeltah: xDelta yDeltah: yDelta
  6898.                                     xDeltav: deltaP12x yDeltav: deltaP12y
  6899.                                     smoothing: smoothingCount sourceMap: sourceMapOop.
  6900.                     skewWord _ skewWord
  6901.                             bitShift: (startBits - bbW)*destPixSize]
  6902.             ifFalse: [skewWord _ self warpSourcePixels: startBits
  6903.                                     xDeltah: xDelta yDeltah: yDelta
  6904.                                     xDeltav: deltaP12x yDeltav: deltaP12y
  6905.                                     smoothing: smoothingCount sourceMap: sourceMapOop].
  6906.  
  6907.         1 to: nWords do:
  6908.             [ :word |        "here is the inner horizontal loop..."
  6909.             mergeWord _ self merge: (skewWord bitAnd: halftoneWord)
  6910.                 with: ((interpreterProxy longAt: destIndex) bitAnd: destMask).
  6911.             interpreterProxy longAt: destIndex
  6912.                 put: ((destMask bitAnd: mergeWord)
  6913.                     bitOr:
  6914.                     (destMask bitInvert32 bitAnd: (interpreterProxy longAt: destIndex))).
  6915.             destIndex _ destIndex + 4.
  6916.             word >= (nWords - 1) ifTrue:
  6917.                 [word = nWords ifFalse:
  6918.                     ["set mask for last word in this row"
  6919.                     destMask _ mask2.
  6920.                     skewWord _ self warpSourcePixels: pixPerWord
  6921.                                     xDeltah: xDelta yDeltah: yDelta
  6922.                                     xDeltav: deltaP12x yDeltav: deltaP12y
  6923.                                     smoothing: smoothingCount sourceMap: sourceMapOop]]
  6924.                 ifFalse:
  6925.                 ["use fullword mask for inner loop"
  6926.                 destMask _ AllOnes.
  6927.                 skewWord _ self warpSourcePixels: pixPerWord
  6928.                                     xDeltah: xDelta yDeltah: yDelta
  6929.                                     xDeltav: deltaP12x yDeltav: deltaP12y
  6930.                                     smoothing: smoothingCount sourceMap: sourceMapOop].
  6931.             ].
  6932.         pAx _ pAx + deltaP12x.
  6933.         pAy _ pAy + deltaP12y.
  6934.         pBx _ pBx + deltaP43x.
  6935.         pBy _ pBy + deltaP43y.
  6936.         destIndex _ destIndex + destDelta]! !
  6937.  
  6938.  
  6939. !BitBltSimulation methodsFor: 'combination rules'!
  6940. addWord: sourceWord with: destinationWord
  6941.     ^sourceWord + destinationWord! !
  6942.  
  6943. !BitBltSimulation methodsFor: 'combination rules'!
  6944. alphaBlend: sourceWord with: destinationWord
  6945.     "Blend sourceWord with destinationWord, assuming both are 32-bit pixels.
  6946.     The source is assumed to have 255*alpha in the high 8 bits of each pixel,
  6947.     while the high 8 bits of the destinationWord will be ignored.
  6948.     The blend produced is alpha*source + (1-alpha)*dest, with
  6949.     the computation being performed independently on each color
  6950.     component.  The high byte of the result will be 0."
  6951.     | alpha unAlpha colorMask result blend shift |
  6952.     self inline: false.
  6953.     alpha _ sourceWord >> 24.  "High 8 bits of source pixel"
  6954.     unAlpha _ 255 - alpha.
  6955.     colorMask _ 16rFF.
  6956.     result _ 0.
  6957.     1 to: 3 do:
  6958.         [:i | shift _ (i-1)*8.
  6959.         blend _ (((sourceWord>>shift bitAnd: colorMask) * alpha)
  6960.                     + ((destinationWord>>shift bitAnd: colorMask) * unAlpha))
  6961.                  + 254 // 255 bitAnd: colorMask.
  6962.         result _ result bitOr: blend<<shift].
  6963.     ^ result
  6964. ! !
  6965.  
  6966. !BitBltSimulation methodsFor: 'combination rules'!
  6967. bitAnd: sourceWord with: destinationWord
  6968.     ^sourceWord bitAnd: destinationWord! !
  6969.  
  6970. !BitBltSimulation methodsFor: 'combination rules'!
  6971. bitAndInvert: sourceWord with: destinationWord
  6972.     ^sourceWord bitAnd: destinationWord bitInvert32! !
  6973.  
  6974. !BitBltSimulation methodsFor: 'combination rules'!
  6975. bitInvertAnd: sourceWord with: destinationWord
  6976.     ^sourceWord bitInvert32 bitAnd: destinationWord! !
  6977.  
  6978. !BitBltSimulation methodsFor: 'combination rules'!
  6979. bitInvertAndInvert: sourceWord with: destinationWord
  6980.     ^sourceWord bitInvert32 bitAnd: destinationWord bitInvert32! !
  6981.  
  6982. !BitBltSimulation methodsFor: 'combination rules'!
  6983. bitInvertDestination: sourceWord with: destinationWord
  6984.     ^destinationWord bitInvert32! !
  6985.  
  6986. !BitBltSimulation methodsFor: 'combination rules'!
  6987. bitInvertOr: sourceWord with: destinationWord
  6988.     ^sourceWord bitInvert32 bitOr: destinationWord! !
  6989.  
  6990. !BitBltSimulation methodsFor: 'combination rules'!
  6991. bitInvertOrInvert: sourceWord with: destinationWord
  6992.     ^sourceWord bitInvert32 bitOr: destinationWord bitInvert32! !
  6993.  
  6994. !BitBltSimulation methodsFor: 'combination rules'!
  6995. bitInvertSource: sourceWord with: destinationWord
  6996.     ^sourceWord bitInvert32! !
  6997.  
  6998. !BitBltSimulation methodsFor: 'combination rules'!
  6999. bitInvertXor: sourceWord with: destinationWord
  7000.     ^sourceWord bitInvert32 bitXor: destinationWord! !
  7001.  
  7002. !BitBltSimulation methodsFor: 'combination rules'!
  7003. bitOr: sourceWord with: destinationWord
  7004.     ^sourceWord bitOr: destinationWord! !
  7005.  
  7006. !BitBltSimulation methodsFor: 'combination rules'!
  7007. bitOrInvert: sourceWord with: destinationWord
  7008.     ^sourceWord bitOr: destinationWord bitInvert32! !
  7009.  
  7010. !BitBltSimulation methodsFor: 'combination rules'!
  7011. bitXor: sourceWord with: destinationWord
  7012.     ^sourceWord bitXor: destinationWord! !
  7013.  
  7014. !BitBltSimulation methodsFor: 'combination rules'!
  7015. clearWord: source with: destination
  7016.     ^ 0! !
  7017.  
  7018. !BitBltSimulation methodsFor: 'combination rules'!
  7019. destinationWord: sourceWord with: destinationWord
  7020.     ^destinationWord! !
  7021.  
  7022. !BitBltSimulation methodsFor: 'combination rules' stamp: 'di 12/30/97 14:46'!
  7023. merge: sourceWord with: destinationWord
  7024.     | mergeFnwith |
  7025.     "Sender warpLoop is too big to include this in-line"
  7026.     self var: #mergeFnwith declareC: 'int (*mergeFnwith)(int, int)'.
  7027.     mergeFnwith _ self cCoerce: (opTable at: combinationRule+1) to: 'int (*)(int, int)'.
  7028.     mergeFnwith.  "null ref for compiler"
  7029.  
  7030.     ^ self mergeFn: sourceWord with: destinationWord! !
  7031.  
  7032. !BitBltSimulation methodsFor: 'combination rules'!
  7033. partitionedAdd: word1 to: word2 nBits: nBits nPartitions: nParts
  7034.     "Add word1 to word2 as nParts partitions of nBits each.
  7035.     This is useful for packed pixels, or packed colors"
  7036.     | mask sum result |
  7037.     mask _ (1 << nBits) - 1.  "partition mask starts at the right"
  7038.     result _ 0.
  7039.     1 to: nParts do:
  7040.         [:i |
  7041.         sum _ (word1 bitAnd: mask) + (word2 bitAnd: mask).
  7042.         sum <= mask  "result must not carry out of partition"
  7043.             ifTrue: [result _ result bitOr: sum]
  7044.             ifFalse: [result _ result bitOr: mask].
  7045.         mask _ mask << nBits  "slide left to next partition"].
  7046.     ^ result
  7047. ! !
  7048.  
  7049. !BitBltSimulation methodsFor: 'combination rules'!
  7050. partitionedAND: word1 to: word2 nBits: nBits nPartitions: nParts
  7051.     "AND word1 to word2 as nParts partitions of nBits each.
  7052.     Any field of word1 not all-ones is treated as all-zeroes.
  7053.     Used for erasing, eg, brush shapes prior to ORing in a color"
  7054.     | mask result |
  7055.     mask _ (1 << nBits) - 1.  "partition mask starts at the right"
  7056.     result _ 0.
  7057.     1 to: nParts do:
  7058.         [:i |
  7059.         (word1 bitAnd: mask) = mask
  7060.             ifTrue: [result _ result bitOr: (word2 bitAnd: mask)].
  7061.         mask _ mask << nBits  "slide left to next partition"].
  7062.     ^ result
  7063. ! !
  7064.  
  7065. !BitBltSimulation methodsFor: 'combination rules'!
  7066. partitionedMax: word1 with: word2 nBits: nBits nPartitions: nParts
  7067.     "Max word1 to word2 as nParts partitions of nBits each"
  7068.     | mask result |
  7069.     mask _ (1 << nBits) - 1.  "partition mask starts at the right"
  7070.     result _ 0.
  7071.     1 to: nParts do:
  7072.         [:i |
  7073.         result _ result bitOr: ((word2 bitAnd: mask) max: (word1 bitAnd: mask)).
  7074.         mask _ mask << nBits  "slide left to next partition"].
  7075.     ^ result
  7076. ! !
  7077.  
  7078. !BitBltSimulation methodsFor: 'combination rules'!
  7079. partitionedMin: word1 with: word2 nBits: nBits nPartitions: nParts
  7080.     "Min word1 to word2 as nParts partitions of nBits each"
  7081.     | mask result |
  7082.     mask _ (1 << nBits) - 1.  "partition mask starts at the right"
  7083.     result _ 0.
  7084.     1 to: nParts do:
  7085.         [:i |
  7086.         result _ result bitOr: ((word2 bitAnd: mask) min: (word1 bitAnd: mask)).
  7087.         mask _ mask << nBits  "slide left to next partition"].
  7088.     ^ result
  7089. ! !
  7090.  
  7091. !BitBltSimulation methodsFor: 'combination rules'!
  7092. partitionedSub: word1 from: word2 nBits: nBits nPartitions: nParts
  7093.     "Subtract word1 from word2 as nParts partitions of nBits each.
  7094.     This is useful for packed pixels, or packed colors"
  7095.     | mask result p1 p2 |
  7096.     mask _ (1 << nBits) - 1.  "partition mask starts at the right"
  7097.     result _ 0.
  7098.     1 to: nParts do:
  7099.         [:i |
  7100.         p1 _ word1 bitAnd: mask.
  7101.         p2 _ word2 bitAnd: mask.
  7102.         p1 < p2  "result is really abs value of thedifference"
  7103.             ifTrue: [result _ result bitOr: p2 - p1]
  7104.             ifFalse: [result _ result bitOr: p1 - p2].
  7105.         mask _ mask << nBits  "slide left to next partition"].
  7106.     ^ result
  7107. ! !
  7108.  
  7109. !BitBltSimulation methodsFor: 'combination rules'!
  7110. pixMask: sourceWord with: destinationWord
  7111.     self inline: false.
  7112.     ^ self partitionedAND: sourceWord bitInvert32 to: destinationWord
  7113.                     nBits: destPixSize nPartitions: pixPerWord! !
  7114.  
  7115. !BitBltSimulation methodsFor: 'combination rules' stamp: 'di 12/27/97 10:39'!
  7116. pixPaint: sourceWord with: destinationWord
  7117.     self inline: false.
  7118.     sourceWord = 0 ifTrue: [^ destinationWord].
  7119.     ^ sourceWord bitOr:
  7120.         (self partitionedAND: sourceWord bitInvert32 to: destinationWord
  7121.                         nBits: destPixSize nPartitions: pixPerWord)! !
  7122.  
  7123. !BitBltSimulation methodsFor: 'combination rules'!
  7124. rgbAdd: sourceWord with: destinationWord
  7125.     self inline: false.
  7126.     destPixSize < 16 ifTrue:
  7127.         ["Add each pixel separately"
  7128.         ^ self partitionedAdd: sourceWord to: destinationWord
  7129.                         nBits: destPixSize nPartitions: pixPerWord].
  7130.     destPixSize = 16 ifTrue:
  7131.         ["Add RGB components of each pixel separately"
  7132.         ^ (self partitionedAdd: sourceWord to: destinationWord
  7133.                         nBits: 5 nPartitions: 3)
  7134.         + ((self partitionedAdd: sourceWord>>16 to: destinationWord>>16
  7135.                         nBits: 5 nPartitions: 3) << 16)]
  7136.     ifFalse:
  7137.         ["Add RGB components of the pixel separately"
  7138.         ^ self partitionedAdd: sourceWord to: destinationWord
  7139.                         nBits: 8 nPartitions: 3]! !
  7140.  
  7141. !BitBltSimulation methodsFor: 'combination rules'!
  7142. rgbDiff: sourceWord with: destinationWord
  7143.     "Subract the pixels in the source and destination, color by color,
  7144.     and return the sum of the absolute value of all the differences.
  7145.     For non-rgb, XOR the two and return the number of differing pixels.
  7146.     Note that the region is not clipped to bit boundaries, but only to the
  7147.     nearest (enclosing) word.  This is because copyLoop does not do
  7148.     pre-merge masking.  For accurate results, you must subtract the
  7149.     values obtained from the left and right fringes."
  7150.     | diff pixMask |
  7151.     self inline: false.
  7152.     destPixSize < 16 ifTrue:
  7153.         ["Just xor and count differing bits if not RGB"
  7154.         diff _ sourceWord bitXor: destinationWord.
  7155.         pixMask _ (1 bitShift: destPixSize) - 1.
  7156.         [diff = 0] whileFalse:
  7157.             [(diff bitAnd: pixMask) ~= 0 ifTrue: [bitCount _ bitCount + 1].
  7158.             diff _ diff >> destPixSize].
  7159.         ^ destinationWord "for no effect"].
  7160.      destPixSize = 16
  7161.         ifTrue:
  7162.         [diff _ (self partitionedSub: sourceWord from: destinationWord
  7163.                         nBits: 5 nPartitions: 3).
  7164.         bitCount _ bitCount + (diff bitAnd: 16r1F)
  7165.                             + (diff>>5 bitAnd: 16r1F)
  7166.                             + (diff>>10 bitAnd: 16r1F).
  7167.         diff _ (self partitionedSub: sourceWord>>16 from: destinationWord>>16
  7168.                         nBits: 5 nPartitions: 3).
  7169.         bitCount _ bitCount + (diff bitAnd: 16r1F)
  7170.                             + (diff>>5 bitAnd: 16r1F)
  7171.                             + (diff>>10 bitAnd: 16r1F)]
  7172.         ifFalse:
  7173.         [diff _ (self partitionedSub: sourceWord from: destinationWord
  7174.                         nBits: 8 nPartitions: 3).
  7175.         bitCount _ bitCount + (diff bitAnd: 16rFF)
  7176.                             + (diff>>8 bitAnd: 16rFF)
  7177.                             + (diff>>16 bitAnd: 16rFF)].
  7178.     ^ destinationWord  "For no effect on dest"! !
  7179.  
  7180. !BitBltSimulation methodsFor: 'combination rules'!
  7181. rgbMax: sourceWord with: destinationWord
  7182.     self inline: false.
  7183.     destPixSize < 16 ifTrue:
  7184.         ["Max each pixel separately"
  7185.         ^ self partitionedMax: sourceWord with: destinationWord
  7186.                         nBits: destPixSize nPartitions: pixPerWord].
  7187.     destPixSize = 16 ifTrue:
  7188.         ["Max RGB components of each pixel separately"
  7189.         ^ (self partitionedMax: sourceWord with: destinationWord
  7190.                         nBits: 5 nPartitions: 3)
  7191.         + ((self partitionedMax: sourceWord>>16 with: destinationWord>>16
  7192.                         nBits: 5 nPartitions: 3) << 16)]
  7193.     ifFalse:
  7194.         ["Max RGB components of the pixel separately"
  7195.         ^ self partitionedMax: sourceWord with: destinationWord
  7196.                         nBits: 8 nPartitions: 3]! !
  7197.  
  7198. !BitBltSimulation methodsFor: 'combination rules'!
  7199. rgbMin: sourceWord with: destinationWord
  7200.     self inline: false.
  7201.     destPixSize < 16 ifTrue:
  7202.         ["Min each pixel separately"
  7203.         ^ self partitionedMin: sourceWord with: destinationWord
  7204.                         nBits: destPixSize nPartitions: pixPerWord].
  7205.     destPixSize = 16 ifTrue:
  7206.         ["Min RGB components of each pixel separately"
  7207.         ^ (self partitionedMin: sourceWord with: destinationWord
  7208.                         nBits: 5 nPartitions: 3)
  7209.         + ((self partitionedMin: sourceWord>>16 with: destinationWord>>16
  7210.                         nBits: 5 nPartitions: 3) << 16)]
  7211.     ifFalse:
  7212.         ["Min RGB components of the pixel separately"
  7213.         ^ self partitionedMin: sourceWord with: destinationWord
  7214.                         nBits: 8 nPartitions: 3]! !
  7215.  
  7216. !BitBltSimulation methodsFor: 'combination rules' stamp: 'di 1/21/98 21:57'!
  7217. rgbMinInvert: wordToInvert with: destinationWord
  7218.     | sourceWord |
  7219.     self inline: false.
  7220.     sourceWord _ wordToInvert bitInvert32.
  7221.     destPixSize < 16 ifTrue:
  7222.         ["Min each pixel separately"
  7223.         ^ self partitionedMin: sourceWord with: destinationWord
  7224.                         nBits: destPixSize nPartitions: pixPerWord].
  7225.     destPixSize = 16 ifTrue:
  7226.         ["Min RGB components of each pixel separately"
  7227.         ^ (self partitionedMin: sourceWord with: destinationWord
  7228.                         nBits: 5 nPartitions: 3)
  7229.         + ((self partitionedMin: sourceWord>>16 with: destinationWord>>16
  7230.                         nBits: 5 nPartitions: 3) << 16)]
  7231.     ifFalse:
  7232.         ["Min RGB components of the pixel separately"
  7233.         ^ self partitionedMin: sourceWord with: destinationWord
  7234.                         nBits: 8 nPartitions: 3]! !
  7235.  
  7236. !BitBltSimulation methodsFor: 'combination rules'!
  7237. rgbSub: sourceWord with: destinationWord
  7238.     self inline: false.
  7239.     destPixSize < 16 ifTrue:
  7240.         ["Sub each pixel separately"
  7241.         ^ self partitionedSub: sourceWord from: destinationWord
  7242.                         nBits: destPixSize nPartitions: pixPerWord].
  7243.     destPixSize = 16 ifTrue:
  7244.         ["Sub RGB components of each pixel separately"
  7245.         ^ (self partitionedSub: sourceWord from: destinationWord
  7246.                         nBits: 5 nPartitions: 3)
  7247.         + ((self partitionedSub: sourceWord>>16 from: destinationWord>>16
  7248.                         nBits: 5 nPartitions: 3) << 16)]
  7249.     ifFalse:
  7250.         ["Sub RGB components of the pixel separately"
  7251.         ^ self partitionedSub: sourceWord from: destinationWord
  7252.                         nBits: 8 nPartitions: 3]! !
  7253.  
  7254. !BitBltSimulation methodsFor: 'combination rules'!
  7255. sourceWord: sourceWord with: destinationWord
  7256.     ^sourceWord! !
  7257.  
  7258. !BitBltSimulation methodsFor: 'combination rules'!
  7259. subWord: sourceWord with: destinationWord
  7260.     ^sourceWord - destinationWord! !
  7261.  
  7262. !BitBltSimulation methodsFor: 'combination rules' stamp: 'di 1/21/98 06:31'!
  7263. tallyIntoMap: sourceWord with: destinationWord
  7264.     "Tally pixels into the color map.  Note that the source should be 
  7265.     specified = destination, in order for the proper color map checks 
  7266.     to be performed at setup.
  7267.     Note that the region is not clipped to bit boundaries, but only to the
  7268.     nearest (enclosing) word.  This is because copyLoop does not do
  7269.     pre-merge masking.  For accurate results, you must subtract the
  7270.     values obtained from the left and right fringes."
  7271.     | mapIndex pixMask shiftWord |
  7272.     colorMap = interpreterProxy nilObject
  7273.         ifTrue: [^ destinationWord "no op"].
  7274.     destPixSize < 16 ifTrue:
  7275.         ["loop through all packed pixels."
  7276.         pixMask _ (1<<destPixSize) - 1.
  7277.         shiftWord _ destinationWord.
  7278.         1 to: pixPerWord do:
  7279.             [:i |
  7280.             mapIndex _ shiftWord bitAnd: pixMask.
  7281.             interpreterProxy storeWord: mapIndex ofObject: colorMap
  7282.                 withValue: (interpreterProxy fetchWord: mapIndex ofObject: colorMap) + 1.
  7283.             shiftWord _ shiftWord >> destPixSize].
  7284.         ^ destinationWord].
  7285.     destPixSize = 16 ifTrue:
  7286.         ["Two pixels  Tally the right half..."
  7287.         mapIndex _ self rgbMap: (destinationWord bitAnd: 16rFFFF) from: 5 to: cmBitsPerColor.
  7288.         interpreterProxy storeWord: mapIndex ofObject: colorMap
  7289.             withValue: (interpreterProxy fetchWord: mapIndex ofObject: colorMap) + 1.
  7290.         "... and then left half"
  7291.         mapIndex _ self rgbMap: destinationWord>>16 from: 5 to: cmBitsPerColor.
  7292.         interpreterProxy storeWord: mapIndex ofObject: colorMap
  7293.             withValue: (interpreterProxy fetchWord: mapIndex ofObject: colorMap) + 1]
  7294.     ifFalse:
  7295.         ["Just one pixel."
  7296.         mapIndex _ self rgbMap: destinationWord from: 8 to: cmBitsPerColor.
  7297.         interpreterProxy storeWord: mapIndex ofObject: colorMap
  7298.             withValue: (interpreterProxy fetchWord: mapIndex ofObject: colorMap) + 1].
  7299.     ^ destinationWord  "For no effect on dest"! !
  7300.  
  7301.  
  7302. !BitBltSimulation methodsFor: 'pixel mapping'!
  7303. deltaFrom: x1 to: x2 nSteps: n
  7304.     "Utility routine for computing Warp increments."
  7305.  
  7306.     x2 > x1
  7307.         ifTrue: [^ x2 - x1 + FixedPt1 // (n+1) + 1]
  7308.         ifFalse: [x2 = x1 ifTrue: [^ 0].
  7309.                 ^ 0 - (x1 - x2 + FixedPt1 // (n+1) + 1)]! !
  7310.  
  7311. !BitBltSimulation methodsFor: 'pixel mapping' stamp: 'di 12/30/97 20:45'!
  7312. pickSourcePixels: nPix nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask
  7313.     "This is intended to be expanded in-line; it merely calls the others"
  7314.     self inline: true.
  7315.     sourcePixSize >= 16 ifTrue:
  7316.         [^ self pickSourcePixelsRGB: nPix nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask].
  7317.     nullMap ifTrue:
  7318.         [^ self pickSourcePixelsNullMap: nPix srcMask: sourcePixMask destMask: destPixMask].
  7319.     ^ self pickSourcePixels: nPix srcMask: sourcePixMask destMask: destPixMask! !
  7320.  
  7321. !BitBltSimulation methodsFor: 'pixel mapping' stamp: 'di 12/30/97 20:46'!
  7322. pickSourcePixels: nPix srcMask: sourcePixMask destMask: destPixMask
  7323.     "This version of pickSourcePixels is for sourcePixSize <= 8
  7324.         and colorMap notNil"
  7325.     "Pick nPix pixels from the source, mapped by the
  7326.     color map, and right-justify them in the resulting destWord."
  7327.     | sourceWord destWord sourcePix destPix |
  7328.     self inline: false.
  7329.     sourceWord _ (interpreterProxy longAt: sourceIndex).
  7330.     destWord _ 0.
  7331.     1 to: nPix do:
  7332.         [:i |
  7333.         sourcePix _ sourceWord >> ((32-sourcePixSize) - srcBitIndex)
  7334.                     bitAnd: sourcePixMask.
  7335.         "look up sourcePix in colorMap"
  7336.         destPix _ (interpreterProxy fetchWord: sourcePix ofObject: colorMap) bitAnd: destPixMask.
  7337.         destWord _ (destWord << destPixSize) bitOr: destPix.
  7338.         (srcBitIndex _ srcBitIndex + sourcePixSize) > 31 ifTrue:
  7339.             [srcBitIndex _ srcBitIndex - 32.
  7340.             sourceIndex _ sourceIndex + 4.
  7341.             sourceWord _ interpreterProxy longAt: sourceIndex]].
  7342.     ^ destWord! !
  7343.  
  7344. !BitBltSimulation methodsFor: 'pixel mapping' stamp: 'di 12/30/97 20:46'!
  7345. pickSourcePixelsNullMap: nPix srcMask: sourcePixMask destMask: destPixMask
  7346.     "This version of pickSourcePixels is for colorMap==nil.
  7347.         SourcePixelSize is also known to be 8 bits or less."
  7348.     "With no color map, pixels are just masked or zero-filled."
  7349.     | sourceWord destWord sourcePix |
  7350.     self inline: false.
  7351.     sourceWord _ (interpreterProxy longAt: sourceIndex).
  7352.     destWord _ 0.
  7353.     1 to: nPix do:
  7354.         [:i |
  7355.         sourcePix _ sourceWord >> ((32-sourcePixSize) - srcBitIndex)
  7356.                     bitAnd: sourcePixMask.
  7357.         destWord _ (destWord << destPixSize) 
  7358.                     bitOr: (sourcePix bitAnd: destPixMask).
  7359.         (srcBitIndex _ srcBitIndex + sourcePixSize) > 31 ifTrue:
  7360.             [srcBitIndex _ srcBitIndex - 32.
  7361.             sourceIndex _ sourceIndex + 4.
  7362.             sourceWord _ interpreterProxy longAt: sourceIndex]].
  7363.     ^ destWord! !
  7364.  
  7365. !BitBltSimulation methodsFor: 'pixel mapping' stamp: 'di 12/30/97 20:46'!
  7366. pickSourcePixelsRGB: nPix nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask
  7367.     "This version of pickSourcePixels is for sourcePixSize >= 16"
  7368.     "Pick nPix pixels from the source, mapped by the
  7369.     color map, and right-justify them in the resulting destWord.
  7370.     Incoming pixels of 16 or 32 bits are first reduced to cmBitsPerColor.
  7371.     With no color map, pixels are just masked or zero-filled or
  7372.     if 16- or 32-bit pixels, the r, g, and b are so treated individually."
  7373.     | sourceWord destWord sourcePix destPix |
  7374.     self inline: false.
  7375.     sourceWord _ (interpreterProxy longAt: sourceIndex).
  7376.     destWord _ 0.
  7377.     1 to: nPix do:
  7378.         [:i |
  7379.         sourcePix _ sourceWord >> ((32-sourcePixSize) - srcBitIndex)
  7380.                     bitAnd: sourcePixMask.
  7381.         nullMap
  7382.         ifTrue:
  7383.             ["Map between RGB pixels"
  7384.             sourcePixSize = 16
  7385.                 ifTrue: [destPix _ self rgbMap: sourcePix from: 5 to: 8]
  7386.                 ifFalse: [destPix _ self rgbMap: sourcePix from: 8 to: 5]]
  7387.         ifFalse:
  7388.             ["RGB pixels first get reduced to cmBitsPerColor"
  7389.             sourcePixSize = 16
  7390.                 ifTrue: [sourcePix _ self rgbMap: sourcePix from: 5 to: cmBitsPerColor]
  7391.                 ifFalse: [sourcePix _ self rgbMap: sourcePix from: 8 to: cmBitsPerColor].
  7392.             "Then look up sourcePix in colorMap"
  7393.             destPix _ (interpreterProxy fetchWord: sourcePix ofObject: colorMap) bitAnd: destPixMask].
  7394.         destWord _ (destWord << destPixSize) bitOr: destPix.
  7395.         (srcBitIndex _ srcBitIndex + sourcePixSize) > 31 ifTrue:
  7396.             [srcBitIndex _ srcBitIndex - 32.
  7397.             sourceIndex _ sourceIndex + 4.
  7398.             sourceWord _ interpreterProxy longAt: sourceIndex]].
  7399.     ^ destWord! !
  7400.  
  7401. !BitBltSimulation methodsFor: 'pixel mapping'!
  7402. rgbMap: sourcePixel from: nBitsIn to: nBitsOut
  7403.     "Convert the given pixel value with nBitsIn bits for each color component to a pixel value with nBitsOut bits for each color component. Typical values for nBitsIn/nBitsOut are 3, 5, or 8."
  7404.     | mask d srcPix destPix |
  7405.     self inline: true.
  7406.     (d _ nBitsOut - nBitsIn) > 0
  7407.         ifTrue:
  7408.             ["Expand to more bits by zero-fill"
  7409.             mask _ (1 << nBitsIn) - 1.  "Transfer mask"
  7410.             srcPix _ sourcePixel << d.
  7411.             mask _ mask << d.
  7412.             destPix _ srcPix bitAnd: mask.
  7413.             mask _ mask << nBitsOut.
  7414.             srcPix _ srcPix << d.
  7415.             ^ destPix + (srcPix bitAnd: mask)
  7416.                      + (srcPix << d bitAnd: mask << nBitsOut)]
  7417.         ifFalse:
  7418.             ["Compress to fewer bits by truncation"
  7419.             d = 0 ifTrue: [^ sourcePixel].  "no compression"
  7420.             sourcePixel = 0 ifTrue: [^ sourcePixel].  "always map 0 (transparent) to 0"
  7421.             d _ nBitsIn - nBitsOut.
  7422.             mask _ (1 << nBitsOut) - 1.  "Transfer mask"
  7423.             srcPix _ sourcePixel >> d.
  7424.             destPix _ srcPix bitAnd: mask.
  7425.             mask _ mask << nBitsOut.
  7426.             srcPix _ srcPix >> d.
  7427.             destPix _ destPix + (srcPix bitAnd: mask)
  7428.                     + (srcPix >> d bitAnd: mask << nBitsOut).
  7429.             destPix = 0 ifTrue: [^ 1].  "Dont fall into transparent by truncation"
  7430.             ^ destPix]! !
  7431.  
  7432. !BitBltSimulation methodsFor: 'pixel mapping' stamp: 'di 12/30/97 20:07'!
  7433. smoothPix: n atXf: xf yf: yf dxh: dxh dyh: dyh dxv: dxv dyv: dyv
  7434.     pixPerWord: srcPixPerWord pixelMask: sourcePixMask
  7435.     sourceMap: sourceMap
  7436.     | sourcePix r g b x y rgb bitsPerColor d nPix maxPix |
  7437.     self inline: false.
  7438.     r _ g _ b _ 0.  "Separate r, g, b components"
  7439.     maxPix _ n*n.
  7440.     x _ xf.  y _ yf.
  7441.     nPix _ 0.  "actual number of pixels (not clipped and not transparent)"
  7442.     0 to: n-1 do:
  7443.         [:i |
  7444.         0 to: n-1 do:
  7445.             [:j |
  7446.             sourcePix _ (self sourcePixAtX: x + (dxh*i) + (dxv*j)  >> BinaryPoint
  7447.                                     y: y + (dyh*i) + (dyv*j)  >> BinaryPoint
  7448.                                     pixPerWord: srcPixPerWord)
  7449.                                     bitAnd: sourcePixMask.
  7450.             (combinationRule=25 "PAINT" and: [sourcePix = 0]) ifFalse:  
  7451.             ["If not clipped and not transparent, then tally rgb values"
  7452.             nPix _ nPix + 1.
  7453.             sourcePixSize < 16
  7454.                 ifTrue: ["Get 24-bit RGB values from sourcemap table"
  7455.                         rgb _ (interpreterProxy fetchWord: sourcePix ofObject: sourceMap) bitAnd: 16rFFFFFF]
  7456.                 ifFalse: ["Already in RGB format"
  7457.                         sourcePixSize = 32
  7458.                         ifTrue: [rgb _ sourcePix bitAnd: 16rFFFFFF]
  7459.                         ifFalse: ["Note could be faster"
  7460.                                 rgb _ self rgbMap: sourcePix from: 5 to: 8]].
  7461.             r _ r + ((rgb >> 16) bitAnd: 16rFF).
  7462.             g _ g + ((rgb >> 8) bitAnd: 16rFF).
  7463.             b _ b + (rgb bitAnd: 16rFF).
  7464.             ]].
  7465.         ].
  7466.     (nPix = 0 or: [combinationRule=25 "PAINT" and: [nPix < (maxPix//2)]])
  7467.         ifTrue: [^ 0  "All pixels were 0, or most were transparent"].
  7468.     colorMap ~= interpreterProxy nilObject
  7469.         ifTrue: [bitsPerColor _ cmBitsPerColor]
  7470.         ifFalse: [destPixSize = 16 ifTrue: [bitsPerColor _ 5].
  7471.                 destPixSize = 32 ifTrue: [bitsPerColor _ 8]].
  7472.     d _ 8 - bitsPerColor.
  7473.     rgb _ ((r // nPix >> d) << (bitsPerColor*2))
  7474.         + ((g // nPix >> d) << bitsPerColor)
  7475.         + ((b // nPix >> d)).
  7476.     rgb = 0 ifTrue: [
  7477.         "only generate zero if pixel is really transparent"
  7478.         (r + g + b) > 0 ifTrue: [rgb _ 1]].
  7479.     colorMap ~= interpreterProxy nilObject
  7480.         ifTrue: [^ interpreterProxy fetchWord: rgb ofObject: colorMap]
  7481.         ifFalse: [^ rgb]
  7482. ! !
  7483.  
  7484. !BitBltSimulation methodsFor: 'pixel mapping'!
  7485. sourcePixAtX: x y: y pixPerWord: srcPixPerWord
  7486.     | sourceWord index |
  7487.     self inline: true.
  7488.     (x < 0 or: [x >= srcWidth]) ifTrue: [^ 0].
  7489.     (y < 0 or: [y >= srcHeight]) ifTrue: [^ 0].
  7490.     index _ (y * sourceRaster + (x // srcPixPerWord) *4).
  7491.                                                 "4 = BaseHeaderSize"
  7492.     sourceWord _ interpreterProxy longAt: sourceBits + 4 + index.
  7493.     ^ sourceWord >> ((32-sourcePixSize) - (x\\srcPixPerWord*sourcePixSize))! !
  7494.  
  7495. !BitBltSimulation methodsFor: 'pixel mapping' stamp: 'di 12/30/97 20:10'!
  7496. warpSourcePixels: nPix xDeltah: xDeltah yDeltah: yDeltah
  7497.     xDeltav: xDeltav yDeltav: yDeltav
  7498.     smoothing: n sourceMap: sourceMapOop
  7499.     "Pick nPix pixels using these x- and y-incs, and map color if necess."
  7500.  
  7501.     | destWord sourcePix sourcePixMask destPixMask srcPixPerWord destPix |
  7502.     self inline: false.
  7503.     sourcePixSize = 32
  7504.         ifTrue: [ sourcePixMask _ -1]
  7505.         ifFalse: [ sourcePixMask _ (1 << sourcePixSize) - 1].
  7506.     destPixSize = 32
  7507.         ifTrue: [ destPixMask _ -1]
  7508.         ifFalse: [ destPixMask _ (1 << destPixSize) - 1].
  7509.     srcPixPerWord _ 32 // sourcePixSize.
  7510.     destWord _ 0.
  7511.     1 to: nPix do:
  7512.         [:i |
  7513.         n > 1
  7514.         ifTrue:
  7515.             ["Average n pixels and compute dest pixel from color map"
  7516.             destPix _ (self smoothPix: n atXf: sx yf: sy
  7517.                 dxh: xDeltah//n dyh: yDeltah//n dxv: xDeltav//n dyv: yDeltav//n
  7518.                 pixPerWord: srcPixPerWord pixelMask: sourcePixMask
  7519.                 sourceMap: sourceMapOop)
  7520.                     bitAnd: destPixMask]
  7521.         ifFalse:
  7522.             ["No smoothing -- just pick pixel and map if difft depths or color map supplied"
  7523.             sourcePix _ (self sourcePixAtX: sx >> BinaryPoint
  7524.                                     y: sy >> BinaryPoint
  7525.                                     pixPerWord: srcPixPerWord)
  7526.                         bitAnd: sourcePixMask.
  7527.             colorMap = interpreterProxy nilObject
  7528.                 ifTrue:
  7529.                 [destPixSize = sourcePixSize
  7530.                 ifTrue:
  7531.                     [destPix _ sourcePix]
  7532.                 ifFalse:
  7533.                     [sourcePixSize >= 16 ifTrue:
  7534.                         ["Map between RGB pixels"
  7535.                         sourcePixSize = 16
  7536.                             ifTrue: [destPix _ self rgbMap: sourcePix from: 5 to: 8]
  7537.                             ifFalse: [destPix _ self rgbMap: sourcePix from: 8 to: 5]]
  7538.                     ifFalse: [destPix _ sourcePix bitAnd: destPixMask]]]
  7539.             ifFalse:
  7540.                 [sourcePixSize >= 16 ifTrue:
  7541.                     ["RGB pixels first get reduced to cmBitsPerColor"
  7542.                     sourcePixSize = 16
  7543.                         ifTrue: [sourcePix _ self rgbMap: sourcePix from: 5 to: cmBitsPerColor]
  7544.                         ifFalse: [sourcePix _ self rgbMap: sourcePix from: 8 to: cmBitsPerColor]].
  7545.                 "Then look up sourcePix in colorMap"
  7546.                 destPix _ (interpreterProxy fetchWord: sourcePix ofObject: colorMap) bitAnd: destPixMask]].
  7547.         destWord _ (destWord << destPixSize) bitOr: destPix.
  7548.         sx _ sx + xDeltah.
  7549.         sy _ sy + yDeltah.
  7550.         ].
  7551.     ^ destWord! !
  7552.  
  7553.  
  7554. !BitBltSimulation methodsFor: 'translation support' stamp: 'di 1/21/98 23:01'!
  7555. initBBOpTable
  7556.     self cCode: 'opTable[0+1] = (int)clearWordwith'.
  7557.     self cCode: 'opTable[1+1] = (int)bitAndwith'.
  7558.     self cCode: 'opTable[2+1] = (int)bitAndInvertwith'.
  7559.     self cCode: 'opTable[3+1] = (int)sourceWordwith'.
  7560.     self cCode: 'opTable[4+1] = (int)bitInvertAndwith'.
  7561.     self cCode: 'opTable[5+1] = (int)destinationWordwith'.
  7562.     self cCode: 'opTable[6+1] = (int)bitXorwith'.
  7563.     self cCode: 'opTable[7+1] = (int)bitOrwith'.
  7564.     self cCode: 'opTable[8+1] = (int)bitInvertAndInvertwith'.
  7565.     self cCode: 'opTable[9+1] = (int)bitInvertXorwith'.
  7566.     self cCode: 'opTable[10+1] = (int)bitInvertDestinationwith'.
  7567.     self cCode: 'opTable[11+1] = (int)bitOrInvertwith'.
  7568.     self cCode: 'opTable[12+1] = (int)bitInvertSourcewith'.
  7569.     self cCode: 'opTable[13+1] = (int)bitInvertOrwith'.
  7570.     self cCode: 'opTable[14+1] = (int)bitInvertOrInvertwith'.
  7571.     self cCode: 'opTable[15+1] = (int)destinationWordwith'.
  7572.     self cCode: 'opTable[16+1] = (int)destinationWordwith'.
  7573.     self cCode: 'opTable[17+1] = (int)destinationWordwith'.
  7574.     self cCode: 'opTable[18+1] = (int)addWordwith'.
  7575.     self cCode: 'opTable[19+1] = (int)subWordwith'.
  7576.     self cCode: 'opTable[20+1] = (int)rgbAddwith'.
  7577.     self cCode: 'opTable[21+1] = (int)rgbSubwith'.
  7578.     self cCode: 'opTable[22+1] = (int)rgbDiffwith'.
  7579.     self cCode: 'opTable[23+1] = (int)tallyIntoMapwith'.
  7580.     self cCode: 'opTable[24+1] = (int)alphaBlendwith'.
  7581.     self cCode: 'opTable[25+1] = (int)pixPaintwith'.
  7582.     self cCode: 'opTable[26+1] = (int)pixMaskwith'.
  7583.     self cCode: 'opTable[27+1] = (int)rgbMaxwith'.
  7584.     self cCode: 'opTable[28+1] = (int)rgbMinwith'.
  7585.     self cCode: 'opTable[29+1] = (int)rgbMinInvertwith'.
  7586.     self cCode: 'opTable[30+1] = (int)destinationWordwith'.
  7587.     self cCode: 'opTable[31+1] = (int)destinationWordwith'.
  7588. ! !
  7589.  
  7590. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7591.  
  7592. BitBltSimulation class
  7593.     instanceVariableNames: ''!
  7594.  
  7595. !BitBltSimulation class methodsFor: 'initialization'!
  7596. initialize
  7597.     "BitBltSimulation initialize"
  7598.  
  7599.     self initializeRuleTable.
  7600.  
  7601.     "Mask constants"
  7602.     AllOnes _ 16rFFFFFFFF.
  7603.     BinaryPoint _ 14.
  7604.     FixedPt1 _ 1 << BinaryPoint.  "Value of 1.0 in Warp's fixed-point representation"
  7605.  
  7606.     "Indices into stopConditions for scanning"
  7607.     EndOfRun _ 257.
  7608.     CrossedX _ 258.
  7609.  
  7610.     "Form fields"
  7611.     FormBitsIndex _ 0.
  7612.     FormWidthIndex _ 1.
  7613.     FormHeightIndex _ 2.
  7614.     FormDepthIndex _ 3.
  7615.  
  7616.     "BitBlt fields"
  7617.     BBDestFormIndex _ 0.
  7618.     BBSourceFormIndex _ 1.
  7619.     BBHalftoneFormIndex _ 2.
  7620.     BBRuleIndex _ 3.
  7621.     BBDestXIndex _ 4.
  7622.     BBDestYIndex _ 5.
  7623.     BBWidthIndex _ 6.
  7624.     BBHeightIndex _ 7.
  7625.     BBSourceXIndex _ 8.
  7626.     BBSourceYIndex _ 9.
  7627.     BBClipXIndex _ 10.
  7628.     BBClipYIndex _ 11.
  7629.     BBClipWidthIndex _ 12.
  7630.     BBClipHeightIndex _ 13.
  7631.     BBColorMapIndex _ 14.
  7632.     BBWarpBase _ 15.
  7633.     BBLastIndex _ 15.
  7634.     BBXTableIndex _ 16.! !
  7635.  
  7636. !BitBltSimulation class methodsFor: 'initialization' stamp: 'di 1/21/98 21:54'!
  7637. initializeRuleTable
  7638.     "BitBltSimulation initializeRuleTable"
  7639.     OpTable _ #(
  7640.         "0" clearWord:with:
  7641.         "1" bitAnd:with:
  7642.         "2" bitAndInvert:with:
  7643.         "3" sourceWord:with:
  7644.         "4" bitInvertAnd:with:
  7645.         "5" destinationWord:with:
  7646.         "6" bitXor:with:
  7647.         "7" bitOr:with:
  7648.         "8" bitInvertAndInvert:with:
  7649.         "9" bitInvertXor:with:
  7650.         "10" bitInvertDestination:with:
  7651.         "11" bitOrInvert:with:
  7652.         "12" bitInvertSource:with:
  7653.         "13" bitInvertOr:with:
  7654.         "14" bitInvertOrInvert:with:
  7655.         "15" destinationWord:with:
  7656.         "16" destinationWord:with:
  7657.         "17" destinationWord:with:
  7658.         "18" addWord:with:
  7659.         "19" subWord:with:
  7660.         "20" rgbAdd:with:
  7661.         "21" rgbSub:with:
  7662.         "22" rgbDiff:with:
  7663.         "23" tallyIntoMap:with:
  7664.         "24" alphaBlend:with:
  7665.         "25" pixPaint:with:
  7666.         "26" pixMask:with:
  7667.         "27" rgbMax:with:
  7668.         "28" rgbMin:with:
  7669.         "29" rgbMinInvert:with:
  7670.         "30" destinationWord:with:
  7671.         "31" destinationWord:with:
  7672.     ).
  7673.     OpTableSize _ OpTable size + 1.  "0-origin indexing"
  7674. ! !
  7675.  
  7676. !BitBltSimulation class methodsFor: 'initialization'!
  7677. test2  "BitBltSimulation test2"
  7678.     | f |
  7679.     Display fillWhite: (0@0 extent: 300@140).
  7680.     1 to: 12 do:
  7681.         [:i | f _ (Form extent: i@5) fillBlack.
  7682.         0 to: 20 do:
  7683.             [:x | f displayOn: Display
  7684.                     at: (x*13) @ (i*10)]]! !
  7685.  
  7686. !BitBltSimulation class methodsFor: 'initialization'!
  7687. timingTest: extent  "BitBltSimulation timingTest: 640@480"
  7688.     | f f2 map |
  7689.     f _ Form extent: extent depth: 8.
  7690.     f2 _ Form extent: extent depth: 8.
  7691.     map _ Bitmap new: 1 << f2 depth.
  7692.     ^ Array with:
  7693.     (Time millisecondsToRun: [100 timesRepeat:
  7694.         [f fillWithColor: Color white]])
  7695.     with:
  7696.     (Time millisecondsToRun: [100 timesRepeat:
  7697.         [f copy: f boundingBox from: 0@0 in: f2 rule: Form over]])
  7698.     with:
  7699.     (Time millisecondsToRun: [100 timesRepeat:
  7700.         [f copyBits: f boundingBox from: f2 at: 0@0 colorMap: map]])! !
  7701.  
  7702.  
  7703. !BitBltSimulation class methodsFor: 'translation' stamp: 'di 12/29/97 20:00'!
  7704. declareCVarsIn: aCCodeGenerator
  7705.     aCCodeGenerator var: 'opTable'
  7706.         declareC: 'int opTable[' , OpTableSize printString , ']'! !
  7707. BitBltSimulation subclass: #BitBltSimulator
  7708.     instanceVariableNames: ''
  7709.     classVariableNames: ''
  7710.     poolDictionaries: ''
  7711.     category: 'Squeak-Interpreter'!
  7712.  
  7713. !BitBltSimulator methodsFor: 'all' stamp: 'di 12/30/97 09:23'!
  7714. initBBOpTable
  7715.     opTable _ OpTable! !
  7716.  
  7717. !BitBltSimulator methodsFor: 'all' stamp: 'di 12/30/97 11:07'!
  7718. mergeFn: arg1 with: arg2
  7719.     ^ self perform: (opTable at: combinationRule+1) with: arg1 with: arg2! !
  7720.  
  7721. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7722.  
  7723. BitBltSimulator class
  7724.     instanceVariableNames: ''!
  7725.  
  7726. !BitBltSimulator class methodsFor: 'translation' stamp: 'ikp 1/3/98 23:10'!
  7727. translate: fileName doInlining: inlineFlag
  7728.     "Time millisecondsToRun: [
  7729.         Interpreter translate: 'interp.c' doInlining: true.
  7730.         Smalltalk beep] 164760 167543 171826 174510"
  7731.     | cg |
  7732.     BitBltSimulation initialize.
  7733.     Interpreter initialize.
  7734.     ObjectMemory initialize.
  7735.     cg _ CCodeGenerator new initialize.
  7736.     cg addClass: BitBltSimulation.
  7737.     cg addClass: Interpreter.
  7738.     cg addClass: ObjectMemory.
  7739.     BitBltSimulation declareCVarsIn: cg.
  7740.     Interpreter declareCVarsIn: cg.
  7741.     ObjectMemory declareCVarsIn: cg.
  7742.     cg storeCodeOnFile: fileName doInlining: inlineFlag.! !
  7743. MouseMenuController subclass: #BitEditor
  7744.     instanceVariableNames: 'scale squareForm color transparent '
  7745.     classVariableNames: 'ColorButtons YellowButtonMenu YellowButtonMessages '
  7746.     poolDictionaries: ''
  7747.     category: 'Graphics-Editors'!
  7748. !BitEditor commentStamp: 'di 5/22/1998 16:32' prior: 0!
  7749. BitEditor comment:
  7750. 'I am a bit-magnifying tool for editing small Forms directly on the display screen. I continue to be active until the user points outside of my viewing area.'!
  7751.  
  7752.  
  7753. !BitEditor methodsFor: 'initialize-release'!
  7754. initialize
  7755.  
  7756.     super initialize.
  7757.     self initializeYellowButtonMenu! !
  7758.  
  7759. !BitEditor methodsFor: 'initialize-release'!
  7760. release
  7761.  
  7762.     super release.
  7763.     squareForm release.
  7764.     squareForm _ nil! !
  7765.  
  7766.  
  7767. !BitEditor methodsFor: 'view access'!
  7768. view: aView
  7769.  
  7770.     super view: aView.
  7771.     scale _ aView transformation scale.    
  7772.     scale _ scale x rounded @ scale y rounded.
  7773.     squareForm _ Form extent: scale depth: aView model depth.
  7774.     squareForm fillBlack! !
  7775.  
  7776.  
  7777. !BitEditor methodsFor: 'basic control sequence'!
  7778. controlInitialize
  7779.  
  7780.     super controlInitialize.
  7781.     Cursor crossHair show! !
  7782.  
  7783. !BitEditor methodsFor: 'basic control sequence'!
  7784. controlTerminate
  7785.  
  7786.     Cursor normal show! !
  7787.  
  7788.  
  7789. !BitEditor methodsFor: 'control defaults'!
  7790. isControlActive
  7791.  
  7792.     ^super isControlActive & sensor blueButtonPressed not 
  7793.         & sensor keyboardPressed not! !
  7794.  
  7795. !BitEditor methodsFor: 'control defaults'!
  7796. redButtonActivity
  7797.     | formPoint displayPoint |
  7798.     model depth = 1 ifTrue:
  7799.         ["If this is just a black&white form, then set the color to be
  7800.         the opposite of what it was where the mouse was clicked"
  7801.         formPoint _ (view inverseDisplayTransform: sensor cursorPoint - (scale//2)) rounded.
  7802.         color _ 1-(view workingForm pixelValueAt: formPoint).
  7803.         squareForm fillColor: (color=1 ifTrue: [Color black] ifFalse: [Color white])].
  7804.     [sensor redButtonPressed]
  7805.       whileTrue: 
  7806.         [formPoint _ (view inverseDisplayTransform: sensor cursorPoint - (scale//2)) rounded.
  7807.         displayPoint _ view displayTransform: formPoint.
  7808.         squareForm 
  7809.             displayOn: Display
  7810.             at: displayPoint 
  7811.             clippingBox: view insetDisplayBox 
  7812.             rule: Form over
  7813.             fillColor: nil.
  7814.         view changeValueAt: formPoint put: color]! !
  7815.  
  7816.  
  7817. !BitEditor methodsFor: 'menu messages'!
  7818. accept
  7819.     "The edited information should now be accepted by the view."
  7820.  
  7821.     view accept! !
  7822.  
  7823. !BitEditor methodsFor: 'menu messages'!
  7824. cancel
  7825.     "The edited informatin should be forgotten by the view."
  7826.  
  7827.     view cancel! !
  7828.  
  7829. !BitEditor methodsFor: 'menu messages' stamp: 'jm 3/27/98 14:52'!
  7830. fileOut
  7831.  
  7832.     | fileName |
  7833.     fileName _ FillInTheBlank
  7834.         request: 'File name?'
  7835.         initialAnswer: 'Filename.form'.
  7836.     fileName isEmpty ifTrue: [^ self].
  7837.     Cursor normal
  7838.         showWhile: [model writeOnFileNamed: fileName].
  7839. ! !
  7840.  
  7841. !BitEditor methodsFor: 'menu messages'!
  7842. setColor: aColor
  7843.     "Set the color that the next edited dots of the model to be the argument, 
  7844.     aSymbol. aSymbol can be any color changing message understood by a 
  7845.     Form, such as white or black."
  7846.  
  7847.     color _ aColor pixelValueForDepth: model depth.
  7848.     squareForm fillColor: aColor.
  7849. ! !
  7850.  
  7851. !BitEditor methodsFor: 'menu messages'!
  7852. setTransparentColor
  7853.     squareForm fillColor: Color gray.
  7854.     color _ model transparentPixelValue! !
  7855.  
  7856. !BitEditor methodsFor: 'menu messages'!
  7857. test
  7858.     view workingForm follow: [Sensor cursorPoint] while: [Sensor noButtonPressed].
  7859.     Sensor waitNoButton! !
  7860.  
  7861.  
  7862. !BitEditor methodsFor: 'private'!
  7863. initializeYellowButtonMenu
  7864.  
  7865.     self yellowButtonMenu: YellowButtonMenu
  7866.         yellowButtonMessages: YellowButtonMessages! !
  7867.  
  7868. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  7869.  
  7870. BitEditor class
  7871.     instanceVariableNames: ''!
  7872.  
  7873. !BitEditor class methodsFor: 'class initialization'!
  7874. initialize
  7875.     "The Bit Editor is the only controller to override the use of the blue
  7876.     button with a different pop-up menu. Initialize this menu."
  7877.  
  7878.     YellowButtonMenu _ PopUpMenu labels:
  7879. 'cancel
  7880. accept
  7881. file out
  7882. test' lines: #(2 3).
  7883.     YellowButtonMessages _ #(cancel accept fileOut test)    
  7884.  
  7885.     "BitEditor initialize"! !
  7886.  
  7887.  
  7888. !BitEditor class methodsFor: 'instance creation'!
  7889. openOnForm: aForm 
  7890.     "Create and schedule a BitEditor on the form aForm at its top left corner. 
  7891.     Show the small and magnified view of aForm."
  7892.  
  7893.     | scaleFactor |
  7894.     scaleFactor _ 8 @ 8.
  7895.     ^self openOnForm: aForm
  7896.         at: (self locateMagnifiedView: aForm scale: scaleFactor) topLeft
  7897.         scale: scaleFactor! !
  7898.  
  7899. !BitEditor class methodsFor: 'instance creation'!
  7900. openOnForm: aForm at: magnifiedLocation 
  7901.     "Create and schedule a BitEditor on the form aForm at magnifiedLocation. 
  7902.     Show the small and magnified view of aForm."
  7903.  
  7904.     ^self openOnForm: aForm
  7905.         at: magnifiedLocation
  7906.         scale: 8 @ 8! !
  7907.  
  7908. !BitEditor class methodsFor: 'instance creation'!
  7909. openOnForm: aForm at: magnifiedLocation scale: scaleFactor 
  7910.     "Create and schedule a BitEditor on the form aForm. Show the small and 
  7911.     magnified view of aForm."
  7912.  
  7913.     | aScheduledView |
  7914.     aScheduledView _ self
  7915.                 bitEdit: aForm
  7916.                 at: magnifiedLocation
  7917.                 scale: scaleFactor
  7918.                 remoteView: nil.
  7919.     aScheduledView controller openDisplayAt:
  7920.         aScheduledView displayBox topLeft + (aScheduledView displayBox extent / 2)! !
  7921.  
  7922. !BitEditor class methodsFor: 'instance creation'!
  7923. openScreenViewOnForm: aForm at: formLocation magnifiedAt: magnifiedLocation scale: scaleFactor
  7924.     "Create and schedule a BitEditor on the form aForm. Show the magnified
  7925.     view of aForm in a scheduled window."
  7926.     | smallFormView bitEditor savedForm r |
  7927.     smallFormView _ FormView new model: aForm.
  7928.     smallFormView align: smallFormView viewport topLeft with: formLocation.
  7929.     bitEditor _ self bitEdit: aForm at: magnifiedLocation scale: scaleFactor remoteView: smallFormView.
  7930.     bitEditor controller blueButtonMenu: nil blueButtonMessages: nil.
  7931.     savedForm _ Form fromDisplay: (r _ bitEditor displayBox expandBy: (0@23 corner: 0@0)).
  7932.     bitEditor controller startUp.
  7933.     savedForm displayOn: Display at: r topLeft.
  7934.     bitEditor release.
  7935.     smallFormView release.
  7936.  
  7937.     "BitEditor magnifyOnScreen."! !
  7938.  
  7939.  
  7940. !BitEditor class methodsFor: 'examples'!
  7941. magnifyOnScreen
  7942.     "Bit editing of an area of the display screen. User designates a 
  7943.     rectangular area that is magnified by 8 to allow individual screens dots to
  7944.     be modified. red button is used to set a bit to black and yellow button is
  7945.     used to set a bit to white. Editor is not scheduled in a view. Original
  7946.     screen location is updated immediately. This is the same as FormEditor
  7947.     magnify."
  7948.     | smallRect smallForm scaleFactor tempRect |
  7949.     scaleFactor _ 8 @ 8.
  7950.     smallRect _ Rectangle fromUser.
  7951.     smallRect isNil ifTrue: [^self].
  7952.     smallForm _ Form fromDisplay: smallRect.
  7953.     tempRect _ self locateMagnifiedView: smallForm scale: scaleFactor.
  7954.     "show magnified form size until mouse is depressed"
  7955.     self
  7956.         openScreenViewOnForm: smallForm 
  7957.         at: smallRect topLeft 
  7958.         magnifiedAt: tempRect topLeft 
  7959.         scale: scaleFactor
  7960.  
  7961.     "BitEditor magnifyOnScreen."! !
  7962.  
  7963. !BitEditor class methodsFor: 'examples'!
  7964. magnifyWithSmall
  7965. "    Also try:
  7966.     BitEditor openOnForm:
  7967.         (Form extent: 32@32 depth: Display depth)
  7968.     BitEditor openOnForm:
  7969.         ((MaskedForm extent: 32@32 depth: Display depth)
  7970.         withTransparentPixelValue: -1)
  7971. "
  7972.     "Open a BitEditor viewing an area on the screen which the user chooses"
  7973.     | area form |
  7974.     area _ Rectangle fromUser.
  7975.     area isNil ifTrue: [^ self].
  7976.     form _ Form fromDisplay: area.
  7977.     self openOnForm: form
  7978.  
  7979.     "BitEditor magnifyWithSmall."! !
  7980.  
  7981.  
  7982. !BitEditor class methodsFor: 'private' stamp: 'di 1/16/98 15:46'!
  7983. bitEdit: aForm at: magnifiedFormLocation scale: scaleFactor remoteView: remoteView
  7984.     "Create a BitEditor on aForm. That is, aForm is a small image that will 
  7985.     change as a result of the BitEditor changing a second and magnified 
  7986.     view of me. magnifiedFormLocation is where the magnified form is to be 
  7987.     located on the screen. scaleFactor is the amount of magnification. This 
  7988.     method implements a scheduled view containing both a small and 
  7989.     magnified view of aForm. Upon accept, aForm is updated."
  7990.  
  7991.     | aFormView scaledFormView bitEditor topView extent menuView lowerRightExtent |
  7992.     scaledFormView _ FormHolderView new model: aForm.
  7993.     scaledFormView scaleBy: scaleFactor.
  7994.     bitEditor _ self new.
  7995.     scaledFormView controller: bitEditor.
  7996.     bitEditor setColor: Color black.
  7997.     topView _ StandardSystemView new.
  7998.     remoteView == nil ifTrue: [topView label: 'Bit Editor'].
  7999.     topView borderWidth: 2.
  8000.  
  8001.     topView addSubView: scaledFormView.
  8002.     remoteView == nil
  8003.         ifTrue:  "If no remote view, then provide a local view of the form"
  8004.             [aFormView _ FormView new model: scaledFormView workingForm.
  8005.             aFormView controller: NoController new.
  8006.             aForm height < 50
  8007.                 ifTrue: [aFormView borderWidthLeft: 0 right: 2 top: 2 bottom: 2]
  8008.                 ifFalse: [aFormView borderWidthLeft: 0 right: 2 top: 2 bottom: 0].
  8009.             topView addSubView: aFormView below: scaledFormView]
  8010.          ifFalse:  "Otherwise, the remote one should view the same form"
  8011.             [remoteView model: scaledFormView workingForm].
  8012.     lowerRightExtent _ remoteView == nil
  8013.             ifTrue:
  8014.                 [(scaledFormView viewport width - aFormView viewport width) @
  8015.                     (aFormView viewport height max: 50)]
  8016.             ifFalse:
  8017.                 [scaledFormView viewport width @ 50].
  8018.     menuView _ self buildColorMenu: lowerRightExtent colorCount: 1.
  8019.     menuView model: bitEditor.
  8020.     menuView borderWidthLeft: 0 right: 0 top: 2 bottom: 0.
  8021.     topView
  8022.         addSubView: menuView
  8023.         align: menuView viewport topRight
  8024.         with: scaledFormView viewport bottomRight.
  8025.     extent _ scaledFormView viewport extent + (0 @ lowerRightExtent y)
  8026.             + (4 @ 4).  "+4 for borders"
  8027.     topView minimumSize: extent.
  8028.     topView maximumSize: extent.
  8029.     topView translateBy: magnifiedFormLocation.
  8030.     topView insideColor: Color white.
  8031.     ^topView! !
  8032.  
  8033. !BitEditor class methodsFor: 'private' stamp: 'jm 4/7/98 20:43'!
  8034. buildColorMenu: extent colorCount: nColors
  8035.     "See BitEditor magnifyWithSmall."
  8036.  
  8037.     | menuView form aSwitchView
  8038.      button formExtent highlightForm color leftOffset |
  8039.     menuView _ FormMenuView new.
  8040.     menuView window: (0@0 corner: extent).
  8041.     formExtent _ 30@30 min: extent//(nColors*2+1@2).  "compute this better"
  8042.     leftOffset _ extent x-(nColors*2-1*formExtent x)//2.
  8043.     highlightForm _ Form extent: formExtent.
  8044.     highlightForm borderWidth: 4.
  8045.     1 to: nColors do: [:index | 
  8046.         color _ (nColors = 1
  8047.             ifTrue: [#(black)]
  8048.             ifFalse: [#(black gray)]) at: index.
  8049.         form _ Form extent: formExtent.
  8050.         form fill: form boundingBox fillColor: (Color perform: color).
  8051.         form borderWidth: 5.
  8052.         form border: form boundingBox width: 4 fillColor: Color white.
  8053.         button _ Button new.
  8054.         index = 1
  8055.             ifTrue: [button onAction: [menuView model setColor: Color fromUser]]
  8056.             ifFalse: [button onAction: [menuView model setTransparentColor]].
  8057.  
  8058.         aSwitchView _ PluggableButtonView
  8059.             on: button
  8060.             getState: #isOn
  8061.             action: #turnOn.
  8062.         aSwitchView
  8063.             shortcutCharacter: ((nColors=3 ifTrue: ['xvn'] ifFalse: ['xn']) at: index);
  8064.             label: form;
  8065.             window: (0@0 extent: form extent);
  8066.             translateBy: (((index - 1) * 2 * form width) + leftOffset)@(form height // 2);
  8067.             borderWidth: 1.
  8068.         menuView addSubView: aSwitchView].
  8069.     ^ menuView
  8070. ! !
  8071.  
  8072. !BitEditor class methodsFor: 'private'!
  8073. locateMagnifiedView: aForm scale: scaleFactor
  8074.     "Answer a rectangle at the location where the scaled view of the form,
  8075.     aForm, should be displayed."
  8076.  
  8077.     ^ Rectangle originFromUser: (aForm extent * scaleFactor + (0@50)).
  8078.     ! !
  8079. ArrayedCollection variableWordSubclass: #Bitmap
  8080.     instanceVariableNames: ''
  8081.     classVariableNames: ''
  8082.     poolDictionaries: ''
  8083.     category: 'Graphics-Support'!
  8084. !Bitmap commentStamp: 'di 5/22/1998 16:32' prior: 0!
  8085. Bitmap comment:
  8086. 'My instances provide contiguous storage of bits, primarily to hold the graphical data of Forms. Forms and their subclasses provide the additional structural information as to how the bits should be interpreted in two dimensions.'!
  8087.  
  8088.  
  8089. !Bitmap methodsFor: 'initialize-release'!
  8090. fromByteStream: aStream 
  8091.     "Initialize the array of bits by reading integers from the argument, 
  8092.     aStream."
  8093.     aStream nextInto: self! !
  8094.  
  8095.  
  8096. !Bitmap methodsFor: 'filing' stamp: 'di 2/19/98 17:03'!
  8097. compress: bm toByteArray: ba
  8098.     "Store a run-coded compression of the receiver into the byteArray ba,
  8099.     and return the last index stored into. ba is assumed to be large enough.
  8100.     The encoding is as follows...
  8101.         S {N D}*.
  8102.         S is the size of the original bitmap, followed by run-coded pairs.
  8103.         N is a run-length * 4 + data code.
  8104.         D, the data, depends on the data code...
  8105.             0    skip N words, D is absent
  8106.             1    N words with all 4 bytes = D (1 byte)
  8107.             2    N words all = D (4 bytes)
  8108.             3    N words follow in D (4N bytes)
  8109.         S and N are encoded as follows...
  8110.             0-223    0-223
  8111.             224-254    (0-30)*256 + next byte (0-7935)
  8112.             255        next 4 bytes"        
  8113.     | size k word j lowByte eqBytes i |
  8114.     <primitive: 237>
  8115.     self var: #bm declareC: 'int *bm'.
  8116.     self var: #ba declareC: 'unsigned char *ba'.
  8117.     size _ bm size.
  8118.     i _ self encodeInt: size in: ba at: 1.
  8119.     k _ 1.
  8120.     [k <= size] whileTrue:
  8121.         [word _ bm at: k.
  8122.         lowByte _ word bitAnd: 16rFF.
  8123.         eqBytes _ ((word >> 8) bitAnd: 16rFF) = lowByte
  8124.                 and: [((word >> 16) bitAnd: 16rFF) = lowByte
  8125.                 and: [((word >> 24) bitAnd: 16rFF) = lowByte]].
  8126.         j _ k.
  8127.         [j < size and: [word = (bm at: j+1)]]  "scan for = words..."
  8128.             whileTrue: [j _ j+1].
  8129.         j > k ifTrue:
  8130.             ["We have two or more = words, ending at j"
  8131.             eqBytes
  8132.                 ifTrue: ["Actually words of = bytes"
  8133.                         i _ self encodeInt: j-k+1*4+1 in: ba at: i.
  8134.                         ba at: i put: lowByte.  i _ i+1]
  8135.                 ifFalse: [i _ self encodeInt: j-k+1*4+2 in: ba at: i.
  8136.                         i _ self encodeBytesOf: word in: ba at: i].
  8137.             k _ j+1]
  8138.             ifFalse:
  8139.             ["Check for word of 4 = bytes"
  8140.             eqBytes ifTrue:
  8141.                 ["Note 1 word of 4 = bytes"
  8142.                 i _ self encodeInt: 1*4+1 in: ba at: i.
  8143.                 ba at: i put: lowByte.  i _ i+1.
  8144.                 k _ k + 1]
  8145.                 ifFalse:
  8146.                 ["Finally, check for junk"
  8147.                 [j < size and: [(bm at: j) ~= (bm at: j+1)]]  "scan for ~= words..."
  8148.                     whileTrue: [j _ j+1].
  8149.                 j = size ifTrue: [j _ j + 1].
  8150.                 "We have one or more unmatching words, ending at j-1"
  8151.                 i _ self encodeInt: j-k*4+3 in: ba at: i.
  8152.                 k to: j-1 do:
  8153.                     [:m | i _ self encodeBytesOf: (bm at: m) in: ba at: i].
  8154.                 k _ j]]].
  8155.     ^ i - 1  "number of bytes actually stored"
  8156. "
  8157. Space check:
  8158.  | n rawBytes myBytes b |
  8159. n _ rawBytes _ myBytes _ 0.
  8160. Form allInstancesDo:
  8161.     [:f | b _ f bits.
  8162.     n _ n + 1.
  8163.     rawBytes _ rawBytes + (b size*4).
  8164.     myBytes _ myBytes + (b compressToByteArray size)].
  8165. Array with: n with: rawBytes with: myBytes
  8166. ColorForms: (116 230324 160318 )
  8167. Forms: (113 1887808 1325055 )
  8168.  
  8169. Integerity check:
  8170. Form allInstances do:
  8171.     [:f | f bits = (Bitmap decompressFromByteArray: f bits compressToByteArray)
  8172.         ifFalse: [self halt]]
  8173.  
  8174. Speed test:
  8175. MessageTally spyOn: [Form allInstances do:
  8176.     [:f | Bitmap decompressFromByteArray: f bits compressToByteArray]]
  8177. "! !
  8178.  
  8179. !Bitmap methodsFor: 'filing' stamp: 'di 2/19/98 16:59'!
  8180. compressToByteArray
  8181.     "Return a run-coded compression of this bitmap into a byteArray"        
  8182.     | byteArray lastByte |
  8183.     "Without skip codes, it is unlikely that the compressed bitmap will be any larger than was the original.  The run-code cases are...
  8184.     N >= 1 words of equal bytes:  4N bytes -> 2 bytes (at worst 4 -> 2)
  8185.     N > 1 equal words:  4N bytes -> 5 bytes (at worst 8 -> 5)
  8186.     N > 1 unequal words:  4N bytes -> 4N + M, where M is the number of bytes required to encode the run length.
  8187.  
  8188. The worst that can happen is that the method begins with unequal words, and than has interspersed occurrences of a word with equal bytes.  Thus we require a run-length at the beginning, and after every interspersed word of equal bytes.  However, each of these saves 2 bytes, so it must be followed by a run of 7936 or more (for which M jumps from 2 to 5) to add any extra overhead.  Therefore the worst case is a series of runs of 7936 or more, with single interspersed words of equal bytes.  At each break we save 2 bytes, but add 5.  Thus the overhead would be no more than 5 + (S//7936*3)."
  8189.     
  8190.     byteArray _ ByteArray new: (self size*4) + 5 + (self size//7936*3).
  8191.     lastByte _ self compress: self toByteArray: byteArray.
  8192.     ^ byteArray copyFrom: 1 to: lastByte! !
  8193.  
  8194. !Bitmap methodsFor: 'filing' stamp: 'di 2/19/98 17:13'!
  8195. decompress: bm fromByteArray: ba at: index
  8196.     "Decompress the body of a byteArray encoded by compressToByteArray (qv)...
  8197.     The format is simply a sequence of run-coded pairs, {N D}*.
  8198.         N is a run-length * 4 + data code.
  8199.         D, the data, depends on the data code...
  8200.             0    skip N words, D is absent
  8201.                 (could be used to skip from one raster line to the next)
  8202.             1    N words with all 4 bytes = D (1 byte)
  8203.             2    N words all = D (4 bytes)
  8204.             3    N words follow in D (4N bytes)
  8205.         S and N are encoded as follows (see decodeIntFrom:)...
  8206.             0-223    0-223
  8207.             224-254    (0-30)*256 + next byte (0-7935)
  8208.             255        next 4 bytes"    
  8209.     "NOTE:  If fed with garbage, this routine could read past the end of ba, but it should fail before writing past the ned of bm."
  8210.     | i code n anInt data end k pastEnd |
  8211.     <primitive: 234>
  8212.     self var: #bm declareC: 'int *bm'.
  8213.     self var: #ba declareC: 'unsigned char *ba'.
  8214.     i _ index.  "byteArray read index"
  8215.     end _ ba size.
  8216.     k _ 1.  "bitmap write index"
  8217.     pastEnd _ bm size + 1.
  8218.     [i <= end] whileTrue:
  8219.         ["Decode next run start N"
  8220.         anInt _ ba at: i.  i _ i+1.
  8221.         anInt <= 223 ifFalse:
  8222.             [anInt <= 254
  8223.                 ifTrue: [anInt _ (anInt-224)*256 + (ba at: i).  i _ i+1]
  8224.                 ifFalse: [anInt _ 0.
  8225.                         1 to: 4 do: [:j | anInt _ (anInt bitShift: 8) + (ba at: i).  i _ i+1]]].
  8226.         n _ anInt >> 2.
  8227.         (k + n) > pastEnd ifTrue: [^ self primitiveFail].
  8228.         code _ anInt bitAnd: 3.
  8229.         code = 0 ifTrue: ["skip"].
  8230.         code = 1 ifTrue: ["n consecutive words of 4 bytes = the following byte"
  8231.                         data _ ba at: i.  i _ i+1.
  8232.                         data _ data bitOr: (data bitShift: 8).
  8233.                         data _ data bitOr: (data bitShift: 16).
  8234.                         1 to: n do: [:j | bm at: k put: data.  k _ k+1]].
  8235.         code = 2 ifTrue: ["n consecutive words = 4 following bytes"
  8236.                         data _ 0.
  8237.                         1 to: 4 do: [:j | data _ (data bitShift: 8) bitOr: (ba at: i).  i _ i+1].
  8238.                         1 to: n do: [:j | bm at: k put: data.  k _ k+1]].
  8239.         code = 3 ifTrue: ["n consecutive words from the data..."
  8240.                         1 to: n do:
  8241.                             [:m | data _ 0.
  8242.                             1 to: 4 do: [:j | data _ (data bitShift: 8) bitOr: (ba at: i).  i _ i+1].
  8243.                             bm at: k put: data.  k _ k+1]]]! !
  8244.  
  8245. !Bitmap methodsFor: 'filing' stamp: 'jm 2/15/98 17:27'!
  8246. encodeBytesOf: anInt in: ba at: i
  8247.     "Copy the integer anInt into byteArray ba at index i, and return the next index"
  8248.  
  8249.     self inline: true.
  8250.     self var: #ba declareC: 'unsigned char *ba'.
  8251.     0 to: 3 do:
  8252.         [:j | ba at: i+j put: (anInt >> (3-j*8) bitAnd: 16rFF)].
  8253.     ^ i+4! !
  8254.  
  8255. !Bitmap methodsFor: 'filing' stamp: 'jm 2/12/98 17:32'!
  8256. encodeInt: int
  8257.     "Encode the integer int as per encodeInt:in:at:, and return it as a ByteArray"
  8258.     | byteArray next |
  8259.     byteArray _ ByteArray new: 5.
  8260.     next _ self encodeInt: int in: byteArray at: 1.
  8261.     ^ byteArray copyFrom: 1 to: next - 1
  8262. ! !
  8263.  
  8264. !Bitmap methodsFor: 'filing' stamp: 'jm 2/15/98 17:26'!
  8265. encodeInt: anInt in: ba at: i
  8266.     "Encode the integer anInt in byteArray ba at index i, and return the next index.
  8267.     The encoding is as follows...
  8268.         0-223    0-223
  8269.         224-254    (0-30)*256 + next byte (0-7935)
  8270.         255        next 4 bytes"        
  8271.  
  8272.     self inline: true.
  8273.     self var: #ba declareC: 'unsigned char *ba'.
  8274.     anInt <= 223 ifTrue: [ba at: i put: anInt. ^ i+1].
  8275.     anInt <= 7935 ifTrue: [ba at: i put: anInt//256+224. ba at: i+1 put: anInt\\256.  ^ i+2].
  8276.     ba at: i put: 255.
  8277.     ^ self encodeBytesOf: anInt in: ba at: i+1! !
  8278.  
  8279. !Bitmap methodsFor: 'filing' stamp: 'di 2/11/98 21:34'!
  8280. readCompressedFrom: strm
  8281.     "Decompress an old-style run-coded stream into this bitmap:
  8282.         [0 means end of runs]
  8283.         [n = 1..127] [(n+3) copies of next byte]
  8284.         [n = 128..191] [(n-127) next bytes as is]
  8285.         [n = 192..255] [(n-190) copies of next 4 bytes]"
  8286.     | n byte out outBuff bytes |
  8287.     out _ WriteStream on: (outBuff _ ByteArray new: self size*4).
  8288.     [(n _ strm next) > 0] whileTrue:
  8289.         [(n between: 1 and: 127) ifTrue:
  8290.             [byte _ strm next.
  8291.             1 to: n+3 do: [:i | out nextPut: byte]].
  8292.         (n between: 128 and: 191) ifTrue:
  8293.             [1 to: n-127 do: [:i | out nextPut: strm next]].
  8294.         (n between: 192 and: 255) ifTrue:
  8295.             [bytes _ (1 to: 4) collect: [:i | strm next].
  8296.             1 to: n-190 do: [:i | bytes do: [:b | out nextPut: b]]]].
  8297.     out position = outBuff size ifFalse: [self error: 'Decompression size error'].
  8298.     "Copy the final byteArray into self"
  8299.     self copyFromByteArray: outBuff.! !
  8300.  
  8301. !Bitmap methodsFor: 'filing' stamp: 'di 10/2/97 00:02'!
  8302. swapBytesFrom: start to: stop
  8303.     "Perform a bigEndian/littleEndian byte reversal of my words"
  8304.     | hack blt |
  8305.     "The implementation is a hack, but fast for large ranges"
  8306.     hack _ Form new hackBits: self.
  8307.     blt _ (BitBlt toForm: hack) sourceForm: hack.
  8308.     blt combinationRule: Form reverse.  "XOR"
  8309.     blt sourceY: start-1; destY: start-1; height: stop-start+1; width: 1.
  8310.     blt sourceX: 0; destX: 3; copyBits.  "Exchange bytes 0 and 3"
  8311.     blt sourceX: 3; destX: 0; copyBits.
  8312.     blt sourceX: 0; destX: 3; copyBits.
  8313.     blt sourceX: 1; destX: 2; copyBits.  "Exchange bytes 1 and 2"
  8314.     blt sourceX: 2; destX: 1; copyBits.
  8315.     blt sourceX: 1; destX: 2; copyBits.
  8316. ! !
  8317.  
  8318. !Bitmap methodsFor: 'filing' stamp: 'jm 2/18/98 14:19'!
  8319. writeOn: aStream 
  8320.     "Store the array of bits onto the argument, aStream. A leading byte of 16r80 identifies this as compressed by compressToByteArray (qv)."
  8321.  
  8322.     | b |
  8323.     aStream nextPut: 16r80.
  8324.     b _ self compressToByteArray.
  8325.     aStream
  8326.         nextPutAll: (self encodeInt: b size);
  8327.         nextPutAll: b.
  8328. ! !
  8329.  
  8330.  
  8331. !Bitmap methodsFor: 'printing'!
  8332. printOn: aStream
  8333.  
  8334.     aStream nextPutAll: 'a Bitmap of length '.
  8335.     self size printOn: aStream! !
  8336.  
  8337.  
  8338. !Bitmap methodsFor: 'accessing'!
  8339. bitPatternForDepth: depth
  8340.     "The raw call on BitBlt needs a Bitmap to represent this color.  I already am Bitmap like.  I am already adjusted for a specific depth.  Interpret me as an array of (32/depth) Color pixelValues.  BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary. 6/18/96 tk"
  8341.  
  8342.     ^ self! !
  8343.  
  8344. !Bitmap methodsFor: 'accessing'!
  8345. byteAt: byteAddress
  8346.     "Extract a byte from a Bitmap.  Note that this is a byte address and it is one-order.  For repeated use, create an instance of BitBlt and use pixelAt:.  See Form pixelAt:  7/1/96 tk"
  8347.     | lowBits |
  8348.     lowBits _ byteAddress - 1 bitAnd: 3.
  8349.     ^((self at: byteAddress - 1 - lowBits // 4 + 1)
  8350.         bitShift: (lowBits - 3) * 8)
  8351.         bitAnd: 16rFF! !
  8352.  
  8353. !Bitmap methodsFor: 'accessing'!
  8354. byteAt: byteAddress put: byte
  8355.     "Insert a byte into a Bitmap.  Note that this is a byte address and it is one-order.  For repeated use, create an instance of BitBlt and use pixelAt:put:.  See Form pixelAt:put:  7/1/96 tk"
  8356.  
  8357.     | longWord shift lowBits longAddr |
  8358.     lowBits _ byteAddress - 1 bitAnd: 3.
  8359.     longWord _ self at: (longAddr _ (byteAddress - 1 - lowBits) // 4 + 1).
  8360.     shift _ (3 - lowBits) * 8.
  8361.     longWord _ longWord - (longWord bitAnd: (16rFF bitShift: shift)) 
  8362.         + (byte bitShift: shift).
  8363.     self at: longAddr put: longWord.
  8364.     ^ byte! !
  8365.  
  8366. !Bitmap methodsFor: 'accessing' stamp: 'di 10/4/97 11:56'!
  8367. copyFromByteArray: byteArray
  8368.     "This method should work with either byte orderings"
  8369.     | long |
  8370.     (self size * 4) = byteArray size ifFalse: [self halt].
  8371.     1 to: byteArray size by: 4 do:
  8372.         [:i | long _ Integer
  8373.                 byte1: (byteArray at: i+3)
  8374.                 byte2: (byteArray at: i+2)
  8375.                 byte3: (byteArray at: i+1)
  8376.                 byte4: (byteArray at: i).
  8377.         self at: i+3//4 put: long]! !
  8378.  
  8379. !Bitmap methodsFor: 'accessing' stamp: 'tk 3/15/97'!
  8380. pixelValueForDepth: depth
  8381.     "Self is being used to represent a single color.  Answer bits that appear in ONE pixel of this color in a Bitmap of the given depth. The depth must be one of 1, 2, 4, 8, 16, or 32.  Returns an integer.  First pixel only.  "
  8382.  
  8383.     ^ (self at: 1) bitAnd: (1 bitShift: depth) - 1! !
  8384.  
  8385. !Bitmap methodsFor: 'accessing'!
  8386. primFill: aPositiveInteger
  8387.     "Fill the receiver, an indexable bytes or words object, with the given positive integer. The range of possible fill values is [0..255] for byte arrays and [0..(2^32 - 1)] for word arrays."
  8388.  
  8389.     <primitive: 145>
  8390.     self errorImproperStore.! !
  8391.  
  8392. !Bitmap methodsFor: 'accessing'!
  8393. replaceFrom: start to: stop with: replacement startingAt: repStart 
  8394.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  8395.     <primitive: 105>
  8396.     super replaceFrom: start to: stop with: replacement startingAt: repStart! !
  8397.  
  8398. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  8399.  
  8400. Bitmap class
  8401.     instanceVariableNames: ''!
  8402.  
  8403. !Bitmap class methodsFor: 'instance creation' stamp: 'di 2/9/98 16:02'!
  8404. decodeIntFrom: s
  8405.     "Decode an integer in stream s as follows...
  8406.         0-223    0-223
  8407.         224-254    (0-30)*256 + next byte (0-7935)
  8408.         255        next 4 bytes    "        
  8409.     | int |
  8410.     int _ s next.
  8411.     int <= 223 ifTrue: [^ int].
  8412.     int <= 254 ifTrue: [^ (int-224)*256 + s next].
  8413.     int _ s next.
  8414.     1 to: 3 do: [:j | int _ (int bitShift: 8) + s next].
  8415.     ^ int! !
  8416.  
  8417. !Bitmap class methodsFor: 'instance creation' stamp: 'di 2/12/98 14:34'!
  8418. decompressFromByteArray: byteArray
  8419.     | s bitmap size |
  8420.     s _ ReadStream on: byteArray.
  8421.     size _ self decodeIntFrom: s.
  8422.     bitmap _ self new: size.
  8423.     bitmap decompress: bitmap fromByteArray: byteArray at: s position+1.
  8424.     ^ bitmap! !
  8425.  
  8426. !Bitmap class methodsFor: 'instance creation' stamp: 'di 2/11/98 21:11'!
  8427. newFromStream: s
  8428.     | len |
  8429.     s next = 16r80 ifTrue:
  8430.         ["New compressed format"
  8431.         len _ self decodeIntFrom: s.
  8432.         ^ Bitmap decompressFromByteArray: (s nextInto: (ByteArray new: len))].
  8433.     s skip: -1.
  8434.     len _ s nextInt32.
  8435.     len <= 0
  8436.         ifTrue: ["Old compressed format"
  8437.                 ^ (self new: len negated) readCompressedFrom: s]
  8438.         ifFalse: ["Old raw data format"
  8439.                 ^ s nextInto: (self new: len)]! !
  8440. ContextPart variableSubclass: #BlockContext
  8441.     instanceVariableNames: 'nargs startpc home '
  8442.     classVariableNames: ''
  8443.     poolDictionaries: ''
  8444.     category: 'Kernel-Methods'!
  8445. !BlockContext commentStamp: 'di 5/22/1998 16:32' prior: 0!
  8446. BlockContext comment:
  8447. 'My instances function similarly to instances of MethodContext, but they hold the dynamic state for execution of a block in Smalltalk. They access all temporary variables and the method sender via their home pointer, so that those values are effectively shared. Their indexable part is used to store their independent value stack during execution.
  8448.     
  8449. My instance must hold onto its home in order to work. This can cause circularities if the home is also pointing (via a temp, perhaps) to the instance. In the rare event that this happens (as in SortedCollection sortBlock:) the message fixTemps will replace home with a copy of home, thus defeating the sharing of temps but, nonetheless, eliminating the circularity.'!
  8450.  
  8451.  
  8452. !BlockContext methodsFor: 'initialize-release'!
  8453. home: aContextPart startpc: position nargs: anInteger 
  8454.     "This is the initialization message. The receiver has been initialized with 
  8455.     the correct size only."
  8456.  
  8457.     home _ aContextPart.
  8458.     startpc _ position.
  8459.     nargs _ anInteger! !
  8460.  
  8461.  
  8462. !BlockContext methodsFor: 'accessing'!
  8463. fixTemps
  8464.     "Fix the values of the temporary variables used in the block that are 
  8465.     ordinarily shared with the method in which the block is defined."
  8466.  
  8467.     home _ home copy.
  8468.     home swapSender: nil! !
  8469.  
  8470. !BlockContext methodsFor: 'accessing'!
  8471. hasMethodReturn
  8472.     "Answer whether the receiver has a return ('^') in its code."
  8473.  
  8474.     | method scanner end |
  8475.     method _ self method.
  8476.     "Determine end of block from long jump preceding it"
  8477.     end _ (method at: startpc-2)\\16-4*256 + (method at: startpc-1) + startpc - 1.
  8478.     scanner _ InstructionStream new method: method pc: startpc.
  8479.     scanner scanFor: [:byte | (byte between: 120 and: 124) or: [scanner pc > end]].
  8480.     ^scanner pc <= end! !
  8481.  
  8482. !BlockContext methodsFor: 'accessing'!
  8483. home
  8484.     "Answer the context in which the receiver was defined."
  8485.  
  8486.     ^home! !
  8487.  
  8488. !BlockContext methodsFor: 'accessing'!
  8489. method
  8490.     "Answer the compiled method in which the receiver was defined."
  8491.  
  8492.     ^home method! !
  8493.  
  8494. !BlockContext methodsFor: 'accessing'!
  8495. numArgs
  8496.  
  8497.     ^nargs! !
  8498.  
  8499. !BlockContext methodsFor: 'accessing'!
  8500. receiver 
  8501.     "Refer to the comment in ContextPart|receiver."
  8502.  
  8503.     ^home receiver! !
  8504.  
  8505. !BlockContext methodsFor: 'accessing'!
  8506. tempAt: index 
  8507.     "Refer to the comment in ContextPart|tempAt:."
  8508.  
  8509.     ^home at: index! !
  8510.  
  8511. !BlockContext methodsFor: 'accessing'!
  8512. tempAt: index put: value 
  8513.     "Refer to the comment in ContextPart|tempAt:put:."
  8514.  
  8515.     ^home at: index put: value! !
  8516.  
  8517.  
  8518. !BlockContext methodsFor: 'evaluating' stamp: 'jm 2/19/98 13:19'!
  8519. ifError: errorHandlerBlock
  8520.     "Evaluate the block represented by the receiver. If an error occurs the given is evaluated with the error message and the receiver as parameters. The error handler block may return a value to be used if the receiver block gets an error. The receiver should not contain an explicit return statement as this would leave an obsolete error handler hanging around."
  8521.     "Examples:
  8522.         [1 whatsUpDoc] ifError: [:err :rcvr | ^ 'huh?'].
  8523.         [1 / 0] ifError: [:err :rcvr |
  8524.             'division by 0' = err
  8525.                 ifTrue: [^ Float inf]
  8526.                 ifFalse: [self error: err]]
  8527. "
  8528.  
  8529.     | lastHandler val activeProcess |
  8530.     activeProcess _ Processor activeProcess.
  8531.     lastHandler _ activeProcess errorHandler.
  8532.     activeProcess errorHandler: [:aString :aReceiver |
  8533.         activeProcess errorHandler: lastHandler.
  8534.         ^ errorHandlerBlock value: aString value: aReceiver].
  8535.     val _ self value.
  8536.     activeProcess errorHandler: lastHandler.
  8537.     ^ val
  8538. ! !
  8539.  
  8540. !BlockContext methodsFor: 'evaluating'!
  8541. value
  8542.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  8543.     block expects any arguments or if the block is already being executed. 
  8544.     Optional. No Lookup. See Object documentation whatIsAPrimitive."
  8545.  
  8546.     <primitive: 81>
  8547.     ^self valueWithArguments: #()! !
  8548.  
  8549. !BlockContext methodsFor: 'evaluating'!
  8550. value: arg 
  8551.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  8552.     block expects other than one argument or if the block is already being 
  8553.     executed. Optional. No Lookup. See Object documentation 
  8554.     whatIsAPrimitive."
  8555.  
  8556.     <primitive: 81>
  8557.     ^self valueWithArguments: (Array with: arg)! !
  8558.  
  8559. !BlockContext methodsFor: 'evaluating'!
  8560. value: arg1 ifError: aBlock
  8561.     "Evaluate the block represented by the receiver. If an error occurs aBlock is evaluated
  8562.      with the error message and the receiver as parameters. The receiver should not contain
  8563.      an explicit return statement as this would leave an obsolete error handler hanging around."
  8564.  
  8565.     | lastHandler val activeProcess |
  8566.     activeProcess _ Processor activeProcess.
  8567.     lastHandler _ activeProcess errorHandler.
  8568.     activeProcess errorHandler: [:aString :aReceiver |
  8569.         activeProcess errorHandler: lastHandler.
  8570.         ^ aBlock value: aString value: aReceiver].
  8571.     val _ self value: arg1.
  8572.     activeProcess errorHandler: lastHandler.
  8573.     ^ val! !
  8574.  
  8575. !BlockContext methodsFor: 'evaluating'!
  8576. value: arg1 value: arg2 
  8577.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  8578.     block expects other than two arguments or if the block is already being 
  8579.     executed. Optional. See Object documentation whatIsAPrimitive."
  8580.  
  8581.     <primitive: 81>
  8582.     ^self valueWithArguments: (Array with: arg1 with: arg2)! !
  8583.  
  8584. !BlockContext methodsFor: 'evaluating'!
  8585. value: arg1 value: arg2 value: arg3 
  8586.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  8587.     block expects other than three arguments or if the block is already being 
  8588.     executed. Optional. See Object documentation whatIsAPrimitive."
  8589.  
  8590.     <primitive: 81>
  8591.     ^self valueWithArguments: 
  8592.         (Array
  8593.             with: arg1
  8594.             with: arg2
  8595.             with: arg3)! !
  8596.  
  8597. !BlockContext methodsFor: 'evaluating' stamp: 'di 11/30/97 09:19'!
  8598. value: arg1 value: arg2 value: arg3 value: arg4 
  8599.     "Primitive. Evaluate the block represented by the receiver. Fail if the 
  8600.     block expects other than three arguments or if the block is already being 
  8601.     executed. Optional. See Object documentation whatIsAPrimitive."
  8602.  
  8603.     <primitive: 81>
  8604.     ^self valueWithArguments: 
  8605.         (Array
  8606.             with: arg1
  8607.             with: arg2
  8608.             with: arg3
  8609.             with: arg4)! !
  8610.  
  8611. !BlockContext methodsFor: 'evaluating'!
  8612. valueWithArguments: anArray 
  8613.     "Primitive. Evaluate the block represented by the receiver. The argument 
  8614.     is an Array whose elements are the arguments for the block. Fail if the 
  8615.     length of the Array is not the same as the the number of arguments that 
  8616.     the block was expecting. Fail if the block is already being executed. 
  8617.     Essential. See Object documentation whatIsAPrimitive."
  8618.  
  8619.     <primitive: 82>
  8620.     self numArgs = anArray size
  8621.         ifTrue: [self error: 'Attempt to evaluate a block that is already being evaluated.']
  8622.         ifFalse: [self error: 'This block requires ' , self numArgs printString , ' arguments.']! !
  8623.  
  8624.  
  8625. !BlockContext methodsFor: 'controlling'!
  8626. whileFalse
  8627.     "Ordinarily compiled in-line, and therefore not overridable.
  8628.     This is in case the message is sent to other than a literal block.
  8629.     Evaluate the receiver, as long as its value is false."
  8630.  
  8631.     ^ [self value] whileFalse: []! !
  8632.  
  8633. !BlockContext methodsFor: 'controlling'!
  8634. whileFalse: aBlock 
  8635.     "Ordinarily compiled in-line, and therefore not overridable.
  8636.     This is in case the message is sent to other than a literal block.
  8637.     Evaluate the argument, aBlock, as long as the value of the receiver is false."
  8638.  
  8639.     ^ [self value] whileFalse: [aBlock value]! !
  8640.  
  8641. !BlockContext methodsFor: 'controlling'!
  8642. whileTrue
  8643.     "Ordinarily compiled in-line, and therefore not overridable.
  8644.     This is in case the message is sent to other than a literal block.
  8645.     Evaluate the receiver, as long as its value is true."
  8646.  
  8647.     ^ [self value] whileTrue: []! !
  8648.  
  8649. !BlockContext methodsFor: 'controlling'!
  8650. whileTrue: aBlock 
  8651.     "Ordinarily compiled in-line, and therefore not overridable.
  8652.     This is in case the message is sent to other than a literal block.
  8653.     Evaluate the argument, aBlock, as long as the value of the receiver is true."
  8654.  
  8655.     ^ [self value] whileTrue: [aBlock value]! !
  8656.  
  8657.  
  8658. !BlockContext methodsFor: 'scheduling'!
  8659. fork
  8660.     "Create and schedule a Process running the code in the receiver."
  8661.  
  8662.     self newProcess resume! !
  8663.  
  8664. !BlockContext methodsFor: 'scheduling'!
  8665. forkAt: priority 
  8666.     "Create and schedule a Process running the code in the receiver. The 
  8667.     priority of the process is the argument, priority."
  8668.  
  8669.     | forkedProcess |
  8670.     forkedProcess _ self newProcess.
  8671.     forkedProcess priority: priority.
  8672.     forkedProcess resume! !
  8673.  
  8674. !BlockContext methodsFor: 'scheduling'!
  8675. newProcess
  8676.     "Answer a Process running the code in the receiver. The process is not 
  8677.     scheduled."
  8678.  
  8679.     ^Process
  8680.         forContext: 
  8681.             [self value.
  8682.             Processor terminateActive]
  8683.         priority: Processor activePriority! !
  8684.  
  8685. !BlockContext methodsFor: 'scheduling'!
  8686. newProcessWith: anArray 
  8687.     "Answer a Process running the code in the receiver. The receiver's block 
  8688.     arguments are bound to the contents of the argument, anArray. The 
  8689.     process is not scheduled."
  8690.  
  8691.     ^Process
  8692.         forContext: 
  8693.             [self valueWithArguments: anArray.
  8694.             Processor terminateActive]
  8695.         priority: Processor activePriority! !
  8696.  
  8697.  
  8698. !BlockContext methodsFor: 'instruction decoding'!
  8699. blockReturnTop
  8700.     "Simulate the interpreter's action when a ReturnTopOfStack bytecode is 
  8701.     encountered in the receiver."
  8702.  
  8703.     | save dest |
  8704.     save _ home.    "Needed because return code will nil it"
  8705.     dest _ self return: self pop to: self sender.
  8706.     home _ save.
  8707.     sender _ nil.
  8708.     ^dest! !
  8709.  
  8710.  
  8711. !BlockContext methodsFor: 'printing'!
  8712. printOn: aStream
  8713.  
  8714.     home == nil ifTrue: [^aStream nextPutAll: 'a BlockContext with home=nil'].
  8715.     aStream nextPutAll: '[] in '.
  8716.     super printOn: aStream! !
  8717.  
  8718.  
  8719. !BlockContext methodsFor: 'private' stamp: 'tk 4/16/1998 15:38'!
  8720. cannotReturn: result
  8721.     "The receiver tried to return result to a method context that no longer exists."
  8722.  
  8723.     Debugger
  8724.         openContext: thisContext
  8725.         label: 'Block cannot return'
  8726.         contents: thisContext shortStack.
  8727. ! !
  8728.  
  8729. !BlockContext methodsFor: 'private'!
  8730. startpc
  8731.     "for use by the System Tracer only"
  8732.  
  8733.     ^startpc! !
  8734.  
  8735. !BlockContext methodsFor: 'private'!
  8736. valueError
  8737.  
  8738.     self error: 'Incompatible number of args, or already active'! !
  8739.  
  8740.  
  8741. !BlockContext methodsFor: 'system simulation'!
  8742. pushArgs: args from: sendr 
  8743.     "Simulates action of the value primitive."
  8744.  
  8745.     args size ~= nargs ifTrue: [^self error: 'incorrect number of args'].
  8746.     stackp _ 0.
  8747.     args do: [:arg | self push: arg].
  8748.     sender _ sendr.
  8749.     pc _ startpc! !
  8750. ParseNode subclass: #BlockNode
  8751.     instanceVariableNames: 'arguments statements returns nArgsNode size remoteCopyNode '
  8752.     classVariableNames: ''
  8753.     poolDictionaries: ''
  8754.     category: 'System-Compiler'!
  8755. !BlockNode commentStamp: 'di 5/22/1998 16:32' prior: 0!
  8756. BlockNode comment:
  8757. 'I represent a bracketed block with 0 or more arguments and 1 or more statements. If I am initialized with no statements, I create one. I have a flag to tell whether my last statement returns a value from the enclosing method. My last three fields remember data needed for code generation. I can emit for value in the usual way, in which case I create a literal method (actually a context remotely copied) to be evaluated by sending it value: at run time. Or I can emit code to be evaluated in line; this only happens at the top level of a method and in conditionals and while-loops, none of which have arguments.'!
  8758.  
  8759.  
  8760. !BlockNode methodsFor: 'initialize-release'!
  8761. arguments: argNodes statements: statementsCollection returns: returnBool from: encoder
  8762.     "Compile."
  8763.  
  8764.     arguments _ argNodes.
  8765.     statements _ statementsCollection size > 0
  8766.                 ifTrue: [statementsCollection]
  8767.                 ifFalse: [argNodes size > 0
  8768.                         ifTrue: [statementsCollection copyWith: arguments last]
  8769.                         ifFalse: [Array with: NodeNil]].
  8770.     returns _ returnBool! !
  8771.  
  8772. !BlockNode methodsFor: 'initialize-release'!
  8773. statements: statementsCollection returns: returnBool 
  8774.     "Decompile."
  8775.  
  8776.     | returnLast |
  8777.     returnLast _ returnBool.
  8778.     returns _ false.
  8779.     statements _ 
  8780.         (statementsCollection size > 1 
  8781.             and: [(statementsCollection at: statementsCollection size - 1) 
  8782.                     isReturningIf])
  8783.                 ifTrue: 
  8784.                     [returnLast _ false.
  8785.                     statementsCollection allButLast]
  8786.                 ifFalse: [statementsCollection size = 0
  8787.                         ifTrue: [Array with: NodeNil]
  8788.                         ifFalse: [statementsCollection]].
  8789.     arguments _ Array new: 0.
  8790.     returnLast ifTrue: [self returnLast]! !
  8791.  
  8792.  
  8793. !BlockNode methodsFor: 'accessing'!
  8794. arguments: argNodes 
  8795.     "Decompile."
  8796.  
  8797.     arguments _ argNodes! !
  8798.  
  8799. !BlockNode methodsFor: 'accessing'!
  8800. firstArgument
  8801.     ^ arguments first! !
  8802.  
  8803. !BlockNode methodsFor: 'accessing'!
  8804. numberOfArguments
  8805.  
  8806.     ^arguments size! !
  8807.  
  8808. !BlockNode methodsFor: 'accessing'!
  8809. returnLast
  8810.  
  8811.     self returns
  8812.         ifFalse: 
  8813.             [returns _ true.
  8814.             statements at: statements size put: statements last asReturnNode]! !
  8815.  
  8816. !BlockNode methodsFor: 'accessing'!
  8817. returnSelfIfNoOther
  8818.  
  8819.     self returns
  8820.         ifFalse: 
  8821.             [statements last == NodeSelf ifFalse: [statements add: NodeSelf].
  8822.             self returnLast]! !
  8823.  
  8824.  
  8825. !BlockNode methodsFor: 'testing'!
  8826. canBeSpecialArgument
  8827.     "Can I be an argument of (e.g.) ifTrue:?"
  8828.  
  8829.     ^arguments size = 0! !
  8830.  
  8831. !BlockNode methodsFor: 'testing'!
  8832. isComplex
  8833.  
  8834.     ^statements size > 1 or: [statements size = 1 and: [statements first isComplex]]! !
  8835.  
  8836. !BlockNode methodsFor: 'testing'!
  8837. isJust: node
  8838.  
  8839.     returns ifTrue: [^false].
  8840.     ^statements size = 1 and: [statements first == node]! !
  8841.  
  8842. !BlockNode methodsFor: 'testing'!
  8843. isJustCaseError
  8844.  
  8845.     ^ statements size = 1 and:
  8846.         [statements first
  8847.             isMessage: #caseError
  8848.             receiver: [:r | r==NodeSelf]
  8849.             arguments: nil]! !
  8850.  
  8851. !BlockNode methodsFor: 'testing'!
  8852. isQuick
  8853.     ^ statements size = 1
  8854.         and: [statements first isVariableReference
  8855.                 or: [statements first isSpecialConstant]]! !
  8856.  
  8857. !BlockNode methodsFor: 'testing'!
  8858. returns
  8859.  
  8860.     ^returns or: [statements last isReturningIf]! !
  8861.  
  8862.  
  8863. !BlockNode methodsFor: 'code generation'!
  8864. code
  8865.  
  8866.     ^statements first code! !
  8867.  
  8868. !BlockNode methodsFor: 'code generation'!
  8869. emitExceptLast: stack on: aStream
  8870.     | nextToLast |
  8871.     nextToLast _ statements size - 1.
  8872.     nextToLast < 1 ifTrue: [^ self].  "Only one statement"
  8873.     1 to: nextToLast - 1 do:
  8874.         [:i | (statements at: i) emitForEffect: stack on: aStream].
  8875.     (returns  "Don't pop before a return"
  8876.             and: [(statements at: nextToLast) prefersValue])
  8877.         ifTrue: [(statements at: nextToLast) emitForValue: stack on: aStream]
  8878.         ifFalse: [(statements at: nextToLast) emitForEffect: stack on: aStream]! !
  8879.  
  8880. !BlockNode methodsFor: 'code generation'!
  8881. emitForEvaluatedEffect: stack on: aStream
  8882.  
  8883.     self returns
  8884.         ifTrue: 
  8885.             [self emitForEvaluatedValue: stack on: aStream.
  8886.             stack pop: 1]
  8887.         ifFalse: 
  8888.             [self emitExceptLast: stack on: aStream.
  8889.             statements last emitForEffect: stack on: aStream]! !
  8890.  
  8891. !BlockNode methodsFor: 'code generation'!
  8892. emitForEvaluatedValue: stack on: aStream
  8893.     self emitExceptLast: stack on: aStream.
  8894.     statements last emitForValue: stack on: aStream.
  8895.     (returns and: [statements size > 1
  8896.             and: [(statements at: statements size-1) prefersValue]])
  8897.         ifTrue: [stack pop: 1]  "compensate for elided pop prior to return"! !
  8898.  
  8899. !BlockNode methodsFor: 'code generation'!
  8900. emitForValue: stack on: aStream
  8901.  
  8902.     aStream nextPut: LdThisContext.
  8903.     stack push: 1.
  8904.     nArgsNode emitForValue: stack on: aStream.
  8905.     remoteCopyNode
  8906.         emit: stack
  8907.         args: 1
  8908.         on: aStream.
  8909.     "Force a two byte jump."
  8910.     self emitLong: size code: JmpLong on: aStream.
  8911.     stack push: arguments size.
  8912.     arguments reverseDo: [:arg | arg emitStorePop: stack on: aStream].
  8913.     self emitForEvaluatedValue: stack on: aStream.
  8914.     self returns ifFalse: [aStream nextPut: EndRemote].
  8915.     stack pop: 1! !
  8916.  
  8917. !BlockNode methodsFor: 'code generation'!
  8918. sizeExceptLast: encoder
  8919.     | codeSize nextToLast |
  8920.     nextToLast _ statements size - 1.
  8921.     nextToLast < 1 ifTrue: [^ 0]. "Only one statement"
  8922.     codeSize _ 0.
  8923.     1 to: nextToLast - 1 do: 
  8924.         [:i | codeSize _ codeSize + ((statements at: i) sizeForEffect: encoder)].
  8925.     ^ (returns  "Don't pop before a return"
  8926.             and: [(statements at: nextToLast) prefersValue])
  8927.         ifTrue: [codeSize + ((statements at: nextToLast) sizeForValue: encoder)]
  8928.         ifFalse: [codeSize + ((statements at: nextToLast) sizeForEffect: encoder)]! !
  8929.  
  8930. !BlockNode methodsFor: 'code generation'!
  8931. sizeForEvaluatedEffect: encoder
  8932.  
  8933.     self returns ifTrue: [^self sizeForEvaluatedValue: encoder].
  8934.     ^(self sizeExceptLast: encoder)
  8935.         + (statements last sizeForEffect: encoder)! !
  8936.  
  8937. !BlockNode methodsFor: 'code generation'!
  8938. sizeForEvaluatedValue: encoder
  8939.  
  8940.     ^(self sizeExceptLast: encoder)
  8941.         + (statements last sizeForValue: encoder)! !
  8942.  
  8943. !BlockNode methodsFor: 'code generation'!
  8944. sizeForValue: encoder
  8945.     nArgsNode _ encoder encodeLiteral: arguments size.
  8946.     remoteCopyNode _ encoder encodeSelector: #blockCopy:.
  8947.     size _ (self sizeForEvaluatedValue: encoder)
  8948.                 + (self returns ifTrue: [0] ifFalse: [1]). "endBlock"
  8949.     arguments _ arguments collect:  "Chance to prepare debugger remote temps"
  8950.                 [:arg | arg asStorableNode: encoder].
  8951.     arguments do: [:arg | size _ size + (arg sizeForStorePop: encoder)].
  8952.     ^1 + (nArgsNode sizeForValue: encoder) 
  8953.         + (remoteCopyNode size: encoder args: 1 super: false) + 2 + size! !
  8954.  
  8955.  
  8956. !BlockNode methodsFor: 'printing'!
  8957. printArgumentsOn: aStream indent: level
  8958.  
  8959.     arguments size = 0
  8960.         ifFalse: 
  8961.             [arguments do: 
  8962.                 [:arg | 
  8963.                 aStream nextPut: $:.
  8964.                 aStream nextPutAll: arg key.
  8965.                 aStream space].
  8966.             aStream nextPutAll: '| '.
  8967.             "If >0 args and >1 statement, put all statements on separate lines"
  8968.             statements size > 1 ifTrue: [aStream crtab: level]]! !
  8969.  
  8970. !BlockNode methodsFor: 'printing'!
  8971. printOn: aStream indent: level
  8972.  
  8973.     statements size <= 1 ifFalse: [aStream crtab: level].
  8974.     aStream nextPut: $[.
  8975.     self printArgumentsOn: aStream indent: level.
  8976.     self printStatementsOn: aStream indent: level.
  8977.     aStream nextPut: $]! !
  8978.  
  8979. !BlockNode methodsFor: 'printing'!
  8980. printStatementsOn: aStream indent: levelOrZero
  8981.     | len shown thisStatement level |
  8982.     level _ 1 max: levelOrZero.
  8983.     comment == nil
  8984.         ifFalse: 
  8985.             [self printCommentOn: aStream indent: level.
  8986.             aStream crtab: level].
  8987.     len _ shown _ statements size.
  8988.     (levelOrZero = 0 "top level" and: [statements last isReturnSelf])
  8989.         ifTrue: [shown _ 1 max: shown - 1]
  8990.         ifFalse: [(len = 1 and: [((statements at: 1) == NodeNil) & (arguments size = 0)])
  8991.                     ifTrue: [shown _ shown - 1]].
  8992.     1 to: shown do: 
  8993.         [:i | 
  8994.         thisStatement _ statements at: i.
  8995.         thisStatement printOn: aStream indent: level.
  8996.         i < shown ifTrue: [aStream nextPut: $.; crtab: level].
  8997.         thisStatement comment size > 0
  8998.             ifTrue: 
  8999.                 [i = shown ifTrue: [aStream crtab: level].
  9000.                 thisStatement printCommentOn: aStream indent: level.
  9001.                 i < shown ifTrue: [aStream crtab: level]]]! !
  9002.  
  9003.  
  9004. !BlockNode methodsFor: 'equation translation'!
  9005. statements
  9006.     ^statements! !
  9007.  
  9008. !BlockNode methodsFor: 'equation translation'!
  9009. statements: val
  9010.     statements _ val! !
  9011.  
  9012.  
  9013. !BlockNode methodsFor: 'C translation'!
  9014. asTranslatorNode
  9015.     | statementList newS |
  9016.     statementList _ OrderedCollection new.
  9017.     statements do: [ :s |
  9018.         newS _ s asTranslatorNode.
  9019.         newS isStmtList ifTrue: [
  9020.             "inline the statement list returned when a CascadeNode is translated"
  9021.             statementList addAll: newS statements.
  9022.         ] ifFalse: [
  9023.             statementList add: newS.
  9024.         ].
  9025.     ].
  9026.     ^TStmtListNode new
  9027.         setArguments: (arguments asArray collect: [ :arg | arg key ])
  9028.         statements: statementList! !
  9029.  
  9030. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9031.  
  9032. BlockNode class
  9033.     instanceVariableNames: ''!
  9034.  
  9035. !BlockNode class methodsFor: 'instance creation'!
  9036. withJust: aNode
  9037.     "Used to create a simple block, eg: withJust: NodeNil"
  9038.     ^ self new statements: (Array with: aNode) returns: false! !
  9039. AlignmentMorph subclass: #BookMorph
  9040.     instanceVariableNames: 'pageSize pages currentPage copyContents newPagePrototype '
  9041.     classVariableNames: 'PageFlipSoundOn '
  9042.     poolDictionaries: ''
  9043.     category: 'Morphic-Widgets'!
  9044.  
  9045. !BookMorph methodsFor: 'initialization' stamp: 'sw 5/6/1998 10:09'!
  9046. addDressing
  9047.     | controlColor pageControls |
  9048.     self addMorph: (Morph new color: color; extent: 10@10).  "spacer"
  9049.     controlColor _ (color saturation > 0.1)
  9050.         ifTrue:
  9051.             [color lighter]
  9052.         ifFalse:
  9053.             [color darker].
  9054.     pageControls _ Preferences noviceMode
  9055.         ifTrue:
  9056.             [self makeKidsPageControlsColored: controlColor]
  9057.         ifFalse:
  9058.             [self makeAuthoringPageControlsColored: controlColor].
  9059.     pageControls borderWidth: 1; inset: 4.
  9060.             
  9061.     self addMorph: pageControls! !
  9062.  
  9063. !BookMorph methodsFor: 'initialization' stamp: 'sw 10/3/97 18:49'!
  9064. addKidsDressing
  9065.     | controlColor pageControls |
  9066.     self addMorph: (Morph new color: color; extent: 10@10).  "spacer"
  9067.     controlColor _ (color saturation > 0.1)
  9068.         ifTrue:
  9069.             [color lighter]
  9070.         ifFalse:
  9071.             [color darker].
  9072.     pageControls _ self makeKidsPageControlsColored: controlColor.
  9073.     pageControls borderWidth: 1; inset: 4.
  9074.             
  9075.     self addMorph: pageControls! !
  9076.  
  9077. !BookMorph methodsFor: 'initialization' stamp: 'sw 10/18/97 18:03'!
  9078. beThoroughlyRepelling
  9079.     submorphs do: [:m | m beRepelling].
  9080.     self beRepelling! !
  9081.  
  9082. !BookMorph methodsFor: 'initialization' stamp: 'sw 8/16/97 13:39'!
  9083. closeCurrentPageToDragNDrop
  9084.     currentPage ifNotNil: [currentPage openToDragNDrop: false]! !
  9085.  
  9086. !BookMorph methodsFor: 'initialization' stamp: 'jm 9/24/97 08:48'!
  9087. initialize
  9088.  
  9089.     super initialize.
  9090.     self setInitialState.
  9091.     pages _ OrderedCollection new.
  9092.     self addDressing.
  9093.     BookMorph turnOffSoundWhile: [self insertPage].
  9094. ! !
  9095.  
  9096. !BookMorph methodsFor: 'initialization' stamp: 'jm 11/17/97 17:26'!
  9097. newPages: pageList currentIndex: index
  9098.     "Replace all my pages with the given list of BookPageMorphs. Make the current page be the page with the given index."
  9099.  
  9100.     pages _ pages species new.
  9101.     pages addAll: pageList.
  9102.     pages isEmpty ifTrue: [^ self insertPage].
  9103.     self goToPage: index.
  9104. ! !
  9105.  
  9106. !BookMorph methodsFor: 'initialization' stamp: 'sw 8/5/97 20:52'!
  9107. removeEverything
  9108.     currentPage _ nil.
  9109.     pages _ OrderedCollection new.
  9110.     super removeAllMorphs! !
  9111.  
  9112. !BookMorph methodsFor: 'initialization' stamp: 'sw 8/12/97 21:31'!
  9113. setInitialState
  9114.     orientation _ #vertical.
  9115.     centering _ #topLeft.
  9116.     hResizing _ #shrinkWrap.
  9117.     vResizing _ #shrinkWrap.
  9118.     inset _ 5.
  9119.     color _ Color white.
  9120.     pageSize _ 160@300.
  9121.     openToDragNDrop _ true.
  9122.     copyContents _ false.! !
  9123.  
  9124.  
  9125. !BookMorph methodsFor: 'accessing' stamp: 'tk 12/18/97 09:44'!
  9126. allNonSubmorphMorphs
  9127.     "Return a collection containing all morphs in this morph which are not currently in the submorph containment hierarchy (put in primarily for bookmorphs)"
  9128.  
  9129.     ^ pages copyWithout: currentPage! !
  9130.  
  9131. !BookMorph methodsFor: 'accessing' stamp: 'sw 11/5/97 13:37'!
  9132. currentPage
  9133.     ^ currentPage! !
  9134.  
  9135. !BookMorph methodsFor: 'accessing' stamp: 'sw 9/20/97 20:29'!
  9136. pageNamed: aName
  9137.     ^ pages detect: [:p | p externalName = aName] ifNone: [nil]! !
  9138.  
  9139. !BookMorph methodsFor: 'accessing'!
  9140. pages
  9141.  
  9142.     ^ pages
  9143. ! !
  9144.  
  9145. !BookMorph methodsFor: 'accessing' stamp: 'tk 8/13/97 17:01'!
  9146. pages: aMorphList
  9147.  
  9148.     pages _ aMorphList asOrderedCollection.
  9149.  
  9150.     "John:  While it is tempting to put this code here, it is wrong.
  9151.     pages size > 0
  9152.         ifTrue: [currentPage _ pages first]
  9153.         ifFalse: [self insertPage].
  9154.     If currentPage is not page 1, then when it comes back in, two pages
  9155. are shown at once!!
  9156.     Just trust the copying mechanism and let currentPage be copied
  9157. correctly. --Ted."! !
  9158.  
  9159. !BookMorph methodsFor: 'accessing'!
  9160. pageSize: aPoint
  9161.  
  9162.     pageSize _ aPoint.
  9163. ! !
  9164.  
  9165.  
  9166. !BookMorph methodsFor: 'dropping/grabbing' stamp: 'sw 10/18/97 18:03'!
  9167. acceptDroppingMorph: aMorph event: evt
  9168.     "Allow the user to add submorphs just by dropping them on this morph."
  9169.  
  9170.     (currentPage allMorphs includes: aMorph)
  9171.         ifFalse: [currentPage addMorph: aMorph]! !
  9172.  
  9173. !BookMorph methodsFor: 'dropping/grabbing'!
  9174. allowSubmorphExtraction
  9175.  
  9176.     ^ false! !
  9177.  
  9178. !BookMorph methodsFor: 'dropping/grabbing' stamp: 'sw 10/18/97 18:19'!
  9179. rootForGrabOf: aMorph
  9180.  
  9181.     | root |
  9182.     (openToDragNDrop or: [copyContents])
  9183.         ifFalse: [^ super rootForGrabOf: aMorph].
  9184.     (aMorph = currentPage or: [aMorph owner = self])
  9185.         ifTrue: [^ self rootForGrabOf: self].
  9186.  
  9187.     root _ aMorph.
  9188.     [root = self] whileFalse:
  9189.         [root owner == currentPage ifTrue:
  9190.             [(copyContents and: [openToDragNDrop not])
  9191.                 ifTrue: [^ root fullCopy]
  9192.                 ifFalse: [^ root]].
  9193.         root _ root owner].
  9194.     ^ super rootForGrabOf: aMorph
  9195. ! !
  9196.  
  9197.  
  9198. !BookMorph methodsFor: 'zooming page turns'!
  9199. goToPage: pageNumber zoomingFrom: srcButtonMorph
  9200.  
  9201.     | bigBalloonMorph i newPage cachedMorph zoomer |
  9202.     pages isEmpty ifTrue: [^ self].
  9203.  
  9204.     (self isInWorld and:
  9205.      [self world modelOrNil respondsTo: #bigBalloonMorph])
  9206.         ifTrue: [bigBalloonMorph _ self world model bigBalloonMorph fullCopy]
  9207.         ifFalse: [^ self goToPage: pageNumber].
  9208.  
  9209.     bigBalloonMorph position: self world model scaffoldingBook root fullBounds origin.
  9210.     bigBalloonMorph removeAllMorphs.
  9211.     i _ pageNumber asInteger.
  9212.     i > pages size ifTrue: [i _ 1].  "wrap"
  9213.     i < 1  ifTrue: [i _ pages size].  "wrap"
  9214.     newPage _ pages at: i.
  9215.     cachedMorph _ CachingMorph new.
  9216.     cachedMorph addMorph: bigBalloonMorph.
  9217.     bigBalloonMorph addMorph: newPage fullCopy.
  9218.     zoomer _ ZoomMorph new.
  9219.     self world addMorphFront: zoomer.
  9220.     zoomer zoomFromMorph: srcButtonMorph
  9221.                             toMorph: cachedMorph
  9222.                             andThen: [self goToPage: i].
  9223.     self world ifNotNil: [self world startSteppingSubmorphsOf: zoomer].
  9224. ! !
  9225.  
  9226. !BookMorph methodsFor: 'zooming page turns'!
  9227. nextPageZoomingFrom: aMorph
  9228.  
  9229.     | i |
  9230.     i _ (pages indexOf: currentPage ifAbsent: [0]) + 1.
  9231.     self goToPage: i zoomingFrom: aMorph.
  9232. ! !
  9233.  
  9234. !BookMorph methodsFor: 'zooming page turns'!
  9235. previousPageZoomingFrom: aMorph
  9236.  
  9237.     | i |
  9238.     i _ (pages indexOf: currentPage ifAbsent: [2]) - 1.
  9239.     self goToPage: i zoomingFrom: aMorph.
  9240. ! !
  9241.  
  9242. !BookMorph methodsFor: 'zooming page turns' stamp: 'di 1/21/98 07:06'!
  9243. showPageTurningFeedbackFromOrigin: oldOrigin ascending: ascending
  9244.     ascending ifNotNil:
  9245.         [self playPageFlipSound.
  9246.         (PageFlipSoundOn and: [oldOrigin ~~ nil]) ifTrue:
  9247.             [Display wipeImage: currentPage imageForm
  9248.                 at: oldOrigin
  9249.                 delta: (ascending ifTrue: [0@-4] ifFalse: [0@4])]]! !
  9250.  
  9251.  
  9252. !BookMorph methodsFor: 'menu' stamp: 'jm 5/15/1998 06:45'!
  9253. addBookMenuItemsTo: aCustomMenu hand: aHandMorph
  9254.     aCustomMenu
  9255.         add: (copyContents
  9256.                 ifTrue: ['don''t be parts bin when closed']
  9257.                 ifFalse: ['be parts bin when closed'])
  9258.         action: #toggleCopyContents.
  9259.     aCustomMenu add: 'previous page' action: #previousPage.
  9260.     aCustomMenu add: 'next page' action: #nextPage.
  9261.     aCustomMenu add: 'insert a page' action: #insertPage.
  9262.     aCustomMenu add: 'delete this page' action: #deletePage.
  9263.     aCustomMenu add: 'page controls' action: #pageControls:.
  9264.     aCustomMenu add: 'sort pages' action: #sortPages:.
  9265.     aCustomMenu add: 'save as new-page prototype' action: #setNewPagePrototype.
  9266.     newPagePrototype ifNotNil: [
  9267.         aCustomMenu add: 'clear new-page prototype' action: #clearNewPagePrototype].
  9268.  
  9269.     (aHandMorph classOfPasteBuffer isKindOf: PasteUpMorph class) ifTrue:
  9270.         [aCustomMenu add: 'paste book page'    action: #pasteBookPage]
  9271. ! !
  9272.  
  9273. !BookMorph methodsFor: 'menu' stamp: 'sw 9/13/97 23:24'!
  9274. addCustomMenuItems: aCustomMenu hand: aHandMorph
  9275.  
  9276.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  9277.     self addBookMenuItemsTo: aCustomMenu hand: aHandMorph
  9278.     "This factoring allows subclasses, such as TabbedPaletteMorph, to choose different items and different wording and still use the super call for the rest of the metamenu"! !
  9279.  
  9280. !BookMorph methodsFor: 'menu' stamp: 'jm 5/14/1998 20:18'!
  9281. clearNewPagePrototype
  9282.     "Clear the new page prototype."
  9283.  
  9284.     newPagePrototype _ nil.
  9285. ! !
  9286.  
  9287. !BookMorph methodsFor: 'menu' stamp: 'sw 10/2/97 15:22'!
  9288. configureForKids
  9289.     super configureForKids.
  9290.     pages do:
  9291.         [:aPage | aPage configureForKids].! !
  9292.  
  9293. !BookMorph methodsFor: 'menu' stamp: 'sw 8/15/97 22:01'!
  9294. deleteControls
  9295.     "If the receiver has an element answering to the name 'Page Controls', delete it"
  9296.  
  9297.     | controls |
  9298.     (controls _ self findSubmorphThat: [:m | m externalName = 'Page Controls'] ifAbsent: [nil]) ifNotNil:
  9299.         [controls delete.
  9300.         self changed]! !
  9301.  
  9302. !BookMorph methodsFor: 'menu'!
  9303. deletePage
  9304.  
  9305.     | oldPage |
  9306.     oldPage _ currentPage.
  9307.     self nextPage.
  9308.     pages remove: oldPage.
  9309.     oldPage delete.
  9310.     currentPage = oldPage ifTrue: [self nextPage].
  9311.     pages isEmpty ifTrue: [self insertPage].
  9312. ! !
  9313.  
  9314. !BookMorph methodsFor: 'menu' stamp: 'sw 8/4/97 12:05'!
  9315. firstPage
  9316.  
  9317.     self goToPage: 1.
  9318. ! !
  9319.  
  9320. !BookMorph methodsFor: 'menu' stamp: 'sw 8/9/97 00:02'!
  9321. insertPage
  9322.     self insertPageColored: self color
  9323. ! !
  9324.  
  9325. !BookMorph methodsFor: 'menu' stamp: 'sw 10/12/97 21:48'!
  9326. insertPage: aPage pageSize: aPageSize
  9327.     ^ self insertPage: aPage pageSize: aPageSize atIndex: (pages size + 1)! !
  9328.  
  9329. !BookMorph methodsFor: 'menu' stamp: 'sw 5/14/1998 11:06'!
  9330. insertPage: aPage pageSize: aPageSize atIndex: anIndex
  9331.  
  9332.     | sz  predecessor |
  9333.     sz _ aPageSize
  9334.         ifNil: [currentPage == nil
  9335.             ifTrue: [pageSize]
  9336.             ifFalse: [currentPage extent]]
  9337.         ifNotNil:
  9338.             [aPageSize].
  9339.     aPage extent: sz.
  9340.     ((pages isEmpty | anIndex == nil) or: [anIndex > pages size])
  9341.         ifTrue:
  9342.             [pages add: aPage]
  9343.         ifFalse:
  9344.             [anIndex <= 1
  9345.                 ifTrue:
  9346.                     [pages addFirst: aPage]
  9347.                 ifFalse:
  9348.                     [predecessor _ anIndex == nil
  9349.                         ifTrue:
  9350.                             [currentPage]
  9351.                         ifFalse:
  9352.                             [pages at: anIndex].
  9353.                     self pages add: aPage after: predecessor]].
  9354.  
  9355.     self goToPageMorph: aPage
  9356. ! !
  9357.  
  9358. !BookMorph methodsFor: 'menu' stamp: 'jm 5/14/1998 20:37'!
  9359. insertPageColored: aColor
  9360.  
  9361.     | sz newPage bw bc |
  9362.     currentPage == nil
  9363.         ifTrue:
  9364.             [sz _ pageSize.
  9365.             bw _ 0.
  9366.             bc _ Color blue muchLighter]
  9367.         ifFalse:
  9368.             [sz _ currentPage extent.
  9369.             bw _ currentPage borderWidth.
  9370.             bc _ currentPage borderColor].
  9371.     newPagePrototype
  9372.         ifNil: [
  9373.             newPage _ PasteUpMorph new extent: sz; color: aColor.
  9374.             newPage borderWidth: bw; borderColor: bc]
  9375.         ifNotNil: [
  9376.             newPage _ newPagePrototype fullCopy].
  9377.     newPage resizeToFit: false.
  9378.     pages isEmpty
  9379.         ifTrue: [pages add: (currentPage _ newPage)]
  9380.         ifFalse: [pages add: newPage after: currentPage].
  9381.     self nextPage.
  9382. ! !
  9383.  
  9384. !BookMorph methodsFor: 'menu' stamp: 'sw 10/2/97 21:31'!
  9385. insertPageShowingString: aString fontName: aName fontSize: aSize
  9386.     "For creating text content on a page of a BookMorph, from cold code.  Sadly, can't yet specify font..."
  9387.     | aTextMorph tempContents |
  9388.     self insertPage.
  9389.     aTextMorph _ TextMorph new.
  9390.     aTextMorph extent: (self extent - (12@0)).
  9391.     aName ifNotNil:
  9392.             [aTextMorph string: aString fontName: aName size: aSize]
  9393.         ifNil:
  9394.             [aTextMorph contentsWrapped: aString].
  9395.     tempContents _ aTextMorph contents.
  9396.     aTextMorph contentsWrapped: '-'.
  9397.     aTextMorph extent: (self extent - (12@0)).
  9398.     aTextMorph contentsWrapped: tempContents.
  9399.  
  9400.     currentPage addMorph: aTextMorph.! !
  9401.  
  9402. !BookMorph methodsFor: 'menu' stamp: 'sw 9/15/97 01:05'!
  9403. insertPageShowingString: aString usingFont: aFont 
  9404.     "For creating text content on a page of a BookMorph, from cold code.  Sadly, can't yet specify font..."
  9405.  
  9406.     self insertPage.
  9407.     currentPage addMorph:
  9408.         (TextMorph new extent: (self extent - (12@0)); contentsWrapped: aString)! !
  9409.  
  9410. !BookMorph methodsFor: 'menu' stamp: 'jm 5/15/1998 06:46'!
  9411. invokeBookMenu
  9412.     "Answer a menu to be popped up from the book-control panel"
  9413.     | aMenu |
  9414.     aMenu _ CustomMenu new.
  9415.     aMenu addList:    #(
  9416.         "    ('border color...'         changeBorderColor:)
  9417.             ('border width...'         changeBorderWidth:)
  9418.             ('lock'                    lock)"
  9419.             ('make bookmark'        bookmarkForThisPage)
  9420.             ('sort pages'                sortPages:)
  9421.             ('remove control panel'    deleteControls)
  9422.         ).
  9423.     (self primaryHand classOfPasteBuffer isKindOf: PasteUpMorph class) ifTrue:
  9424.         [aMenu add: 'paste book page'    action: #pasteBookPage].
  9425.  
  9426.     aMenu add: 'save as new-page prototype' action: #setNewPagePrototype.
  9427.     newPagePrototype ifNotNil: [
  9428.         aMenu add: 'clear new-page prototype' action: #clearNewPagePrototype].
  9429.  
  9430.     aMenu add: (openToDragNDrop ifTrue: ['close'] ifFalse: ['open']) , ' dragNdrop'
  9431.             action: #openCloseDragNDrop.
  9432.  
  9433.     aMenu invokeOn: self defaultSelection: nil! !
  9434.  
  9435. !BookMorph methodsFor: 'menu' stamp: 'sw 8/4/97 12:05'!
  9436. lastPage
  9437.     self goToPage: pages size
  9438. ! !
  9439.  
  9440. !BookMorph methodsFor: 'menu' stamp: 'sw 8/5/97 21:13'!
  9441. newTextMorph
  9442.     "Create a new, empty TextMorph that can be placed in this book."
  9443.  
  9444.     self isInWorld ifTrue:
  9445.         [self primaryHand attachMorph:
  9446.             (TextMorph new extent: currentPage width@30)].
  9447. ! !
  9448.  
  9449. !BookMorph methodsFor: 'menu' stamp: 'sw 10/1/97 00:18'!
  9450. nextPage
  9451.  
  9452.     | i |
  9453.     currentPage == nil ifTrue: [^ self goToPage: 1].
  9454.     i _ (pages indexOf: currentPage ifAbsent: [0]) + 1.
  9455.     self goToPage: i.
  9456. ! !
  9457.  
  9458. !BookMorph methodsFor: 'menu' stamp: 'sw 10/2/97 21:39'!
  9459. pageControls: evt
  9460.  
  9461.     | buttonPanel |
  9462.     buttonPanel _ self makePageControls.
  9463.     buttonPanel borderWidth: 1; inset: 4.
  9464.     evt hand attachMorph: buttonPanel.
  9465. ! !
  9466.  
  9467. !BookMorph methodsFor: 'menu' stamp: 'sw 5/14/1998 11:04'!
  9468. pasteBookPage
  9469.     | aPage |
  9470.     aPage _ self primaryHand objectToPaste.
  9471.  
  9472.     self insertPage: aPage pageSize: aPage extent atIndex: ((pages indexOf: currentPage) - 1).
  9473.     "self goToPageMorph: aPage"! !
  9474.  
  9475. !BookMorph methodsFor: 'menu' stamp: 'sw 8/11/97 23:40'!
  9476. previousPage
  9477.  
  9478.     | i |
  9479.     i _ (pages indexOf: currentPage ifAbsent: [2]) - 1.
  9480.     self goToPage: i.
  9481. ! !
  9482.  
  9483. !BookMorph methodsFor: 'menu' stamp: 'jm 5/14/1998 20:17'!
  9484. setNewPagePrototype
  9485.     "Record the current page as the prototype to be copied when inserting new pages."
  9486.  
  9487.     currentPage ifNotNil:
  9488.         [newPagePrototype _ currentPage fullCopy].
  9489. ! !
  9490.  
  9491. !BookMorph methodsFor: 'menu' stamp: 'jm 11/17/97 17:33'!
  9492. sortPages: evt
  9493.  
  9494.     | sorter |
  9495.     sorter _ BookPageSorterMorph new forBook: self.
  9496.     sorter pageHolder cursor: (pages indexOf: currentPage ifAbsent: [0]).
  9497.     evt == nil
  9498.         ifTrue: [self world addMorphFront: sorter]
  9499.         ifFalse: [evt hand attachMorph: sorter].
  9500. ! !
  9501.  
  9502. !BookMorph methodsFor: 'menu' stamp: 'jm 7/8/97 10:44'!
  9503. toggleCopyContents
  9504.     "Toggle this morph's ability to behave like a parts bin when closed."
  9505.  
  9506.     copyContents _ copyContents not.
  9507. ! !
  9508.  
  9509.  
  9510. !BookMorph methodsFor: 'private' stamp: 'sw 5/13/1998 11:46'!
  9511. authorControlSpecs
  9512.     ^ #(    
  9513.             ( '<--'        firstPage        'Go to first page')
  9514.             ( '<-'         previousPage    'Go to previous page')
  9515.             ('-'            deletePage        'Delete current page')
  9516.             ('<<>>'        invokeBookMenu 'Get a menu')
  9517.             ('+'            insertPage        'Insert new page after this one')
  9518.             ('->'            nextPage        'Go to next page')
  9519.             ( '-->'        lastPage            'Go to final page'))! !
  9520.  
  9521. !BookMorph methodsFor: 'private' stamp: 'sw 8/12/97 12:16'!
  9522. bookmarkForThisPage
  9523.  
  9524.     | b |
  9525.     b _ SimpleButtonMorph new target: self.
  9526.     b actionSelector: #goToPageMorph:.
  9527.     b label: 'Bookmark'.
  9528.     b arguments: (Array with: currentPage).
  9529.     self primaryHand attachMorph: b
  9530. ! !
  9531.  
  9532. !BookMorph methodsFor: 'private' stamp: 'sw 5/13/1998 15:11'!
  9533. goToPage: pageNumber
  9534.  
  9535.     | pageIndex  oldOrigin aWorld oldRect oldPageNumber ascending |
  9536.     pages isEmpty ifTrue: [^ self].
  9537.  
  9538.     oldPageNumber _ pages indexOf: currentPage ifAbsent: [1].
  9539.  
  9540.     pageIndex _ pageNumber asInteger.
  9541.     pageNumber < 1 ifTrue: [pageIndex _ pages size].
  9542.     pageNumber > pages size ifTrue: [pageIndex _ 1].
  9543.  
  9544.  
  9545.     ascending _ oldPageNumber < pageIndex.
  9546.     oldPageNumber = pageIndex ifTrue: [ascending _ nil].
  9547.  
  9548.     (aWorld _ self world) ifNotNil:
  9549.         [self primaryHand newKeyboardFocus: nil].
  9550.     currentPage ifNotNil:
  9551.         [(oldRect _ currentPage screenRectangle) ifNotNil:
  9552.             [oldOrigin _ oldRect origin].
  9553.         currentPage releaseCachedState; delete].
  9554.     currentPage _ pages at: pageIndex.
  9555.     self addMorphBack: currentPage.
  9556.     aWorld ifNotNil:
  9557.         [self world startSteppingSubmorphsOf: currentPage.
  9558.         self showPageTurningFeedbackFromOrigin: oldOrigin ascending: ascending]! !
  9559.  
  9560. !BookMorph methodsFor: 'private' stamp: 'jm 7/1/97 16:43'!
  9561. goToPageMorph: aMorph
  9562.  
  9563.     | i |
  9564.     i _ pages indexOf: aMorph.
  9565.     i = 0 ifFalse: [self goToPage: i].
  9566. ! !
  9567.  
  9568. !BookMorph methodsFor: 'private' stamp: 'sw 4/30/1998 12:16'!
  9569. goToPageMorphNamed: aName
  9570.     | aMorph |
  9571.     aMorph _ pages detect: [:p | p externalName = aName] ifNone: [^ self beep].
  9572.     self goToPageMorph: aMorph! !
  9573.  
  9574. !BookMorph methodsFor: 'private' stamp: 'di 5/6/1998 21:10'!
  9575. insertPageLabel: labelString morphs: morphList
  9576.  
  9577.     | m c labelAllowance |
  9578.     self insertPage.
  9579.     labelString ifNotNil:
  9580.             [m _ (TextMorph new extent: currentPage width@20; contents: labelString).
  9581.         m lock.
  9582.         m position: currentPage position + (((currentPage width - m width) // 2) @ 5).
  9583.         currentPage addMorph: m.
  9584.         labelAllowance _ 40]
  9585.         ifNil:
  9586.             [labelAllowance _ 0].
  9587.  
  9588.     "use a column to align the given morphs, then add them to the page"
  9589.     c _ AlignmentMorph newColumn centering: #center.
  9590.     c addAllMorphs: morphList.
  9591.     c position: currentPage position + (0 @ labelAllowance).
  9592.     currentPage addAllMorphs: morphList.
  9593.     ^ currentPage
  9594. ! !
  9595.  
  9596. !BookMorph methodsFor: 'private' stamp: 'di 5/6/1998 21:10'!
  9597. insertPageLabel: labelString morphs: firstColMorphs secondColumnMorphs: secondColMorphs
  9598.  
  9599.     | c |
  9600.     self insertPageLabel: labelString morphs: firstColMorphs.
  9601.  
  9602.     "use a column to align the given morphs, then add them to the page"
  9603.     c _ AlignmentMorph newColumn centering: #center.
  9604.     c addAllMorphs: secondColMorphs.
  9605.     c position: currentPage position + (100@40).
  9606.     currentPage addAllMorphs: secondColMorphs.
  9607. ! !
  9608.  
  9609. !BookMorph methodsFor: 'private' stamp: 'sw 10/18/97 18:03'!
  9610. kidControlSpecs
  9611.     true ifTrue: [^ self minimalKidsControlSpecs].
  9612.  
  9613.     ^ #(    
  9614.             ( '<--'        firstPage        'Go to first page')
  9615.             ( '<-'         previousPage    'Go to previous page')
  9616.             ('->'            nextPage        'Go to next page')
  9617.             ( '-->'        lastPage            'Go to final page'))! !
  9618.  
  9619. !BookMorph methodsFor: 'private' stamp: 'sw 10/2/97 18:49'!
  9620. makeAuthoringPageControlsColored: aColor
  9621.     ^ self makePageControlsFrom: self authorControlSpecs color: aColor! !
  9622.  
  9623. !BookMorph methodsFor: 'private' stamp: 'sw 10/2/97 18:50'!
  9624. makeKidsPageControlsColored: aColor
  9625.     ^ self makePageControlsFrom: self kidControlSpecs color: aColor! !
  9626.  
  9627. !BookMorph methodsFor: 'private' stamp: 'sw 5/21/1998 18:08'!
  9628. makeMinimalControlsWithColor: aColor title: aString
  9629.  
  9630.     | aButton aColumn aRow but |
  9631.     aButton _ SimpleButtonMorph new target: self; borderColor: Color black; color: aColor; borderWidth: 0.
  9632.     aColumn _ AlignmentMorph newColumn.
  9633.     aColumn color: aButton color; borderWidth: 0; inset: 0.
  9634.     aColumn hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.
  9635.  
  9636.     aRow _ AlignmentMorph newRow.
  9637.     aRow color: aButton color; borderWidth: 0; inset: 0.
  9638.     aRow hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.
  9639.  
  9640.     aRow addMorphBack: (but _ aButton fullCopy label: ' < ' ; actionSelector: #previousPage).
  9641.     but setBalloonText: 'Go to previous page'.
  9642.  
  9643.     aRow addMorphBack: (StringMorph contents: aString) lock.
  9644.  
  9645.     aRow addMorphBack: (but _ aButton fullCopy label: ' > ' ; actionSelector: #nextPage).
  9646.     but setBalloonText: 'Go to next page'.
  9647.  
  9648.     aColumn addMorphBack: aRow.
  9649.  
  9650.     aColumn setNameTo: 'Page Controls'.
  9651.     
  9652.     ^ aColumn! !
  9653.  
  9654. !BookMorph methodsFor: 'private' stamp: 'di 5/6/1998 21:10'!
  9655. makePageControls
  9656.  
  9657.     | b c r |
  9658.     b _ SimpleButtonMorph new target: self; borderColor: Color black.
  9659.     c _ AlignmentMorph newColumn.
  9660.     c color: b color; borderWidth: 0; inset: 0.
  9661.     c hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.
  9662.  
  9663.     r _ AlignmentMorph newRow.
  9664.     r color: b color; borderWidth: 0; inset: 0.
  9665.     r hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.
  9666.     r addMorphBack: (b fullCopy label: '<-';            actionSelector: #previousPage).
  9667.     r addMorphBack: (b fullCopy label: 'Insert';        actionSelector: #insertPage).
  9668.     r addMorphBack: (b fullCopy label: 'Delete';        actionSelector: #deletePage).
  9669.     r addMorphBack: (b fullCopy label: 'Text';        actionSelector: #newTextMorph).
  9670.     r addMorphBack: (b fullCopy label: '->';            actionSelector: #nextPage).
  9671.     c addMorphBack: r.
  9672.  
  9673.     r _ r copy removeAllMorphs.
  9674.     r addMorphBack: (b fullCopy label: 'Bookmark';    actionSelector: #bookmarkForThisPage).
  9675.     r addMorphBack: (b fullCopy label: 'Save';        actionSelector: #saveBookToFile).
  9676.     c addMorphBack: r.
  9677.     
  9678.     ^ c
  9679. ! !
  9680.  
  9681. !BookMorph methodsFor: 'private' stamp: 'sw 5/7/1998 09:06'!
  9682. makePageControlsFrom: controlSpecs color: aColor
  9683.  
  9684.     | aButton aColumn aRow but |
  9685.     aButton _ SimpleButtonMorph new target: self; borderColor: Color black; color: aColor.
  9686.     aColumn _ AlignmentMorph newColumn.
  9687.     aColumn color: aButton color; borderWidth: 0; inset: 0.
  9688.     aColumn hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.
  9689.  
  9690.     aRow _ AlignmentMorph newRow.
  9691.     aRow color: aButton color; borderWidth: 0; inset: 0.
  9692.     aRow hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.
  9693.     controlSpecs do:
  9694.         [:pair | aRow addMorphBack: (but _ aButton fullCopy label: pair first; actionSelector: pair second).
  9695.         but setBalloonText: pair third.
  9696.         (pair last includesSubString: 'enu')
  9697.             ifTrue: [but actWhen: #buttonDown]].
  9698.     aColumn addMorphBack: aRow.
  9699.  
  9700.     aColumn setNameTo: 'Page Controls'.
  9701.     
  9702.     ^ aColumn! !
  9703.  
  9704. !BookMorph methodsFor: 'private' stamp: 'sw 10/18/97 18:03'!
  9705. minimalKidsControlSpecs
  9706.     ^ #(    
  9707.             ( '<-'         previousPage    'Go to previous page')
  9708.             ('->'            nextPage        'Go to next page'))! !
  9709.  
  9710. !BookMorph methodsFor: 'private' stamp: 'jm 5/16/1998 10:39'!
  9711. playPageFlipSound
  9712.  
  9713.     (self world soundsEnabled "user-controllable" and:
  9714.         [PageFlipSoundOn])  "mechanism to suppress sounds at init time"
  9715.             ifTrue: [self playSoundNamed: 'camera'].
  9716. ! !
  9717.  
  9718. !BookMorph methodsFor: 'private' stamp: 'jm 2/11/98 12:24'!
  9719. releaseCachedState
  9720.     "Release the cached state of all my pages."
  9721.  
  9722.     super releaseCachedState.
  9723.     pages do: [:page | page allMorphsDo: [:m | m releaseCachedState]].
  9724. ! !
  9725.  
  9726. !BookMorph methodsFor: 'private' stamp: 'jm 7/1/97 16:55'!
  9727. saveBookToFile
  9728.     "Save this book in a file."
  9729.  
  9730.     | fileName s |
  9731.     fileName _ FillInTheBlank request: 'File name for this Book?'.
  9732.     fileName isEmpty ifTrue: [^ self].  "abort"
  9733.  
  9734.     s _ SmartRefStream newFileNamed: fileName, '.morph'.
  9735.     s nextPut: self fullCopy.
  9736.     s close.
  9737. ! !
  9738.  
  9739. !BookMorph methodsFor: 'private' stamp: 'sw 8/12/97 12:30'!
  9740. switchToAuthorMode
  9741.     "Replace the control panel with one specially for authoring"
  9742.     
  9743.     self deleteControls.
  9744.     self addMorph: ((self makeAuthoringPageControlsColored: self color lighter) borderWidth: 1; inset: 4)
  9745.  
  9746. ! !
  9747.  
  9748.  
  9749. !BookMorph methodsFor: 'copying' stamp: 'tk 8/13/97 15:00'!
  9750. copyRecordingIn: dict
  9751.     "Overridden to copy the pages of this book as well."
  9752.  
  9753.     | new |
  9754.     new _ super copyRecordingIn: dict.
  9755.     new pages: (pages collect: [:pg |
  9756.         "the current page was copied with the submorphs"
  9757.         (dict includesKey: pg)
  9758.             ifTrue: [dict at: pg]  "current page; already copied"
  9759.             ifFalse: [pg copyRecordingIn: dict]]).
  9760.     ^ new
  9761. ! !
  9762.  
  9763. !BookMorph methodsFor: 'copying' stamp: 'jm 7/1/97 17:06'!
  9764. updateReferencesUsing: aDictionary
  9765.  
  9766.     super updateReferencesUsing: aDictionary.
  9767.     pages do: [:page |
  9768.         page allMorphsDo: [:m | m updateReferencesUsing: aDictionary]].
  9769. ! !
  9770.  
  9771.  
  9772. !BookMorph methodsFor: 'object fileIn' stamp: 'di 5/21/1998 19:23'!
  9773. convertbosfcepbbochvimolppcc0: varDict bosfcepcbbochvimolppccn0: smartRefStrm
  9774.     "These variables are automatically stored into the new instance ('pageSize' 'pages' 'currentPage' 'copyContents' ).
  9775.     This method is for additional changes. Use statements like (foo _ varDict at: 'foo')."
  9776.  
  9777.     "Be sure to to fill in ('newPagePrototype' ) and deal with the information in ()"! !
  9778.  
  9779. !BookMorph methodsFor: 'object fileIn' stamp: 'jm 9/24/97 08:49'!
  9780. convertbosfcepbbochvimolppccs0: varDict bosfcepbbochvimolppcc0: smartRefStrm
  9781.     "These variables are automatically stored into the new instance ('pageSize' 'pages' 'currentPage' 'copyContents' ).
  9782.     This method is for additional changes. Use statements like (foo _ varDict at: 'foo')."
  9783.  
  9784.     "Be sure to to fill in () and deal with the information in ('saveBlock' )"! !
  9785.  
  9786. !BookMorph methodsFor: 'object fileIn' stamp: 'jm 5/15/1998 06:59'!
  9787. convertbosfcepcbbochvimolppcc0: varDict bosfcepcbbochvimolppccn0: smartRefStrm
  9788.     "Adding newPagePrototype instance variable."
  9789.     
  9790.     newPagePrototype _ nil.
  9791. ! !
  9792.  
  9793. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  9794.  
  9795. BookMorph class
  9796.     instanceVariableNames: ''!
  9797.  
  9798. !BookMorph class methodsFor: 'all' stamp: 'sw 5/13/1998 11:43'!
  9799. authoringPrototype
  9800.     "Answer an instance of the receiver suitable for placing in a parts bin for authors"
  9801.     
  9802.     | book |
  9803.     book _ self new markAsPartsDonor.
  9804.     book removeEverything; pageSize: 128@102; color: (Color r: 0.9 g: 0.9 b: 0.9).
  9805.     book borderWidth: 1; borderColor: Color black.
  9806.     book addDressing; insertPage.
  9807.     ^ book! !
  9808.  
  9809. !BookMorph class methodsFor: 'all' stamp: 'jm 9/24/97 08:42'!
  9810. initialize
  9811.     "BookMorph initialize"
  9812.  
  9813.     PageFlipSoundOn _ true.
  9814. ! !
  9815.  
  9816. !BookMorph class methodsFor: 'all' stamp: 'jm 9/24/97 08:47'!
  9817. turnOffSoundWhile: aBlock
  9818.     "Turn off page flip sound during the given block."
  9819.  
  9820.     | old |
  9821.     old _ PageFlipSoundOn.
  9822.     PageFlipSoundOn _ false.
  9823.     aBlock value.
  9824.     PageFlipSoundOn _ old.
  9825. ! !
  9826. AlignmentMorph subclass: #BookPageSorterMorph
  9827.     instanceVariableNames: 'book pageHolder '
  9828.     classVariableNames: ''
  9829.     poolDictionaries: ''
  9830.     category: 'Morphic-Widgets'!
  9831.  
  9832. !BookPageSorterMorph methodsFor: 'all' stamp: 'jm 11/17/97 17:42'!
  9833. acceptSort
  9834.  
  9835.     | pages |
  9836.     pages _ OrderedCollection new.
  9837.     pageHolder submorphsDo: [:m |
  9838.         (m isKindOf: BookPageThumbnailMorph) ifTrue: [pages add: m page]].
  9839.     book newPages: pages currentIndex: pageHolder cursor.
  9840.     self delete.
  9841. ! !
  9842.  
  9843. !BookPageSorterMorph methodsFor: 'all' stamp: 'di 5/6/1998 21:09'!
  9844. addControls
  9845.  
  9846.     | b r |
  9847.     b _ SimpleButtonMorph new target: self; borderColor: Color black.
  9848.     r _ AlignmentMorph newRow.
  9849.     r color: b color; borderWidth: 0; inset: 0.
  9850.     r hResizing: #shrinkWrap; vResizing: #shrinkWrap; extent: 5@5.
  9851.     r centering: #topLeft.
  9852.     r addMorphBack: (b fullCopy label: 'Okay';    actionSelector: #acceptSort).
  9853.     r addMorphBack: (b fullCopy label: 'Cancel';    actionSelector: #cancelSort).
  9854.     self addMorphBack: r.
  9855. ! !
  9856.  
  9857. !BookPageSorterMorph methodsFor: 'all' stamp: 'jm 11/17/97 15:14'!
  9858. cancelSort
  9859.  
  9860.     self delete.
  9861. ! !
  9862.  
  9863. !BookPageSorterMorph methodsFor: 'all' stamp: 'jm 11/17/97 19:06'!
  9864. forBook: aBookMorph
  9865.  
  9866.     book _ aBookMorph.
  9867.     pageHolder removeAllMorphs.
  9868.     pageHolder addAllMorphs:
  9869.         (book pages collect: [:p | BookPageThumbnailMorph new page: p]).
  9870.     pageHolder extent: pageHolder width@pageHolder fullBounds height.
  9871. ! !
  9872.  
  9873. !BookPageSorterMorph methodsFor: 'all' stamp: 'jm 11/17/97 19:40'!
  9874. initialize
  9875.  
  9876.     super initialize.
  9877.     self extent: 440@400;
  9878.         orientation: #vertical;
  9879.         centering: #topLeft;
  9880.         hResizing: #spaceFill;
  9881.         vResizing: #spaceFill;
  9882.         inset: 3;
  9883.         color: Color lightGray;
  9884.         borderWidth: 2.
  9885.     pageHolder _ HolderMorph new extent: self extent - borderWidth.
  9886.     pageHolder cursor: 0.
  9887.     self addControls.
  9888.     self addMorphBack: pageHolder.
  9889. ! !
  9890.  
  9891. !BookPageSorterMorph methodsFor: 'all' stamp: 'jm 11/17/97 16:46'!
  9892. pageHolder
  9893.  
  9894.     ^ pageHolder
  9895. ! !
  9896. SketchMorph subclass: #BookPageThumbnailMorph
  9897.     instanceVariableNames: 'page '
  9898.     classVariableNames: ''
  9899.     poolDictionaries: ''
  9900.     category: 'Morphic-Widgets'!
  9901.  
  9902. !BookPageThumbnailMorph methodsFor: 'all' stamp: 'jm 11/17/97 17:45'!
  9903. computeThumbnail
  9904.  
  9905.     | f scale |
  9906.     f _ page imageForm.
  9907.     scale _ self height / f height.  "keep height invariant"
  9908.     self form: (f magnify: f boundingBox by: scale@scale smoothing: 2).
  9909. ! !
  9910.  
  9911. !BookPageThumbnailMorph methodsFor: 'all' stamp: 'jm 11/17/97 14:01'!
  9912. initialize
  9913.  
  9914.     | f |
  9915.     super initialize.
  9916.     color _ Color lightGray.  "background color"
  9917.     f _ Form extent: 60@80 depth: 16.
  9918.     f fill: f boundingBox fillColor: color.
  9919.     self form: f.
  9920. ! !
  9921.  
  9922. !BookPageThumbnailMorph methodsFor: 'all' stamp: 'jm 11/17/97 17:30'!
  9923. page
  9924.  
  9925.     ^ page
  9926. ! !
  9927.  
  9928. !BookPageThumbnailMorph methodsFor: 'all' stamp: 'jm 11/17/97 17:31'!
  9929. page: aBookPageMorph
  9930.  
  9931.     page _ aBookPageMorph.
  9932.     self computeThumbnail.
  9933. ! !
  9934. Object subclass: #Boolean
  9935.     instanceVariableNames: ''
  9936.     classVariableNames: ''
  9937.     poolDictionaries: ''
  9938.     category: 'Kernel-Objects'!
  9939. !Boolean commentStamp: 'di 5/22/1998 16:32' prior: 0!
  9940. Boolean comment:
  9941. 'I represent logical values, providing boolean operations and conditional control structures.'!
  9942.  
  9943.  
  9944. !Boolean methodsFor: 'logical operations'!
  9945. & aBoolean 
  9946.     "Evaluating conjunction. Evaluate the argument. Then answer true if 
  9947.     both the receiver and the argument are true."
  9948.  
  9949.     self subclassResponsibility! !
  9950.  
  9951. !Boolean methodsFor: 'logical operations'!
  9952. eqv: aBoolean 
  9953.     "Answer true if the receiver is equivalent to aBoolean."
  9954.  
  9955.     ^self == aBoolean! !
  9956.  
  9957. !Boolean methodsFor: 'logical operations'!
  9958. not
  9959.     "Negation. Answer true if the receiver is false, answer false if the 
  9960.     receiver is true."
  9961.  
  9962.     self subclassResponsibility! !
  9963.  
  9964. !Boolean methodsFor: 'logical operations'!
  9965. xor: aBoolean 
  9966.     "Exclusive OR. Answer true if the receiver is not equivalent to aBoolean."
  9967.  
  9968.     ^(self == aBoolean) not! !
  9969.  
  9970. !Boolean methodsFor: 'logical operations'!
  9971. | aBoolean 
  9972.     "Evaluating disjunction (OR). Evaluate the argument. Then answer true 
  9973.     if either the receiver or the argument is true."
  9974.  
  9975.     self subclassResponsibility! !
  9976.  
  9977.  
  9978. !Boolean methodsFor: 'controlling'!
  9979. and: alternativeBlock 
  9980.     "Nonevaluating conjunction. If the receiver is true, answer the value of 
  9981.     the argument, alternativeBlock; otherwise answer false without 
  9982.     evaluating the argument."
  9983.  
  9984.     self subclassResponsibility! !
  9985.  
  9986. !Boolean methodsFor: 'controlling'!
  9987. ifFalse: alternativeBlock 
  9988.     "If the receiver is true (i.e., the condition is true), then the value is the 
  9989.     true alternative, which is nil. Otherwise answer the result of evaluating 
  9990.     the argument, alternativeBlock. Create an error notification if the 
  9991.     receiver is nonBoolean. Execution does not actually reach here because 
  9992.     the expression is compiled in-line."
  9993.  
  9994.     self subclassResponsibility! !
  9995.  
  9996. !Boolean methodsFor: 'controlling'!
  9997. ifFalse: falseAlternativeBlock ifTrue: trueAlternativeBlock 
  9998.     "Same as ifTrue:ifFalse:."
  9999.  
  10000.     self subclassResponsibility! !
  10001.  
  10002. !Boolean methodsFor: 'controlling'!
  10003. ifTrue: alternativeBlock 
  10004.     "If the receiver is false (i.e., the condition is false), then the value is the 
  10005.     false alternative, which is nil. Otherwise answer the result of evaluating 
  10006.     the argument, alternativeBlock. Create an error notification if the 
  10007.     receiver is nonBoolean. Execution does not actually reach here because 
  10008.     the expression is compiled in-line."
  10009.  
  10010.     self subclassResponsibility! !
  10011.  
  10012. !Boolean methodsFor: 'controlling'!
  10013. ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock
  10014.     "If the receiver is true (i.e., the condition is true), then answer the value 
  10015.     of the argument trueAlternativeBlock. If the receiver is false, answer the 
  10016.     result of evaluating the argument falseAlternativeBlock. If the receiver 
  10017.     is a nonBoolean then create an error notification. Execution does not 
  10018.     actually reach here because the expression is compiled in-line."
  10019.  
  10020.     self subclassResponsibility! !
  10021.  
  10022. !Boolean methodsFor: 'controlling'!
  10023. or: alternativeBlock 
  10024.     "Nonevaluating disjunction. If the receiver is false, answer the value of 
  10025.     the argument, alternativeBlock; otherwise answer true without 
  10026.     evaluating the argument."
  10027.  
  10028.     self subclassResponsibility! !
  10029.  
  10030.  
  10031. !Boolean methodsFor: 'copying'!
  10032. deepCopy 
  10033.     "Receiver has two concrete subclasses, True and False.
  10034.     Only one instance of each should be made, so return self."! !
  10035.  
  10036. !Boolean methodsFor: 'copying'!
  10037. shallowCopy 
  10038.     "Receiver has two concrete subclasses, True and False.
  10039.     Only one instance of each should be made, so return self."! !
  10040.  
  10041.  
  10042. !Boolean methodsFor: 'printing' stamp: 'sw 4/25/1998 12:51'!
  10043. basicType
  10044.     ^ #boolean! !
  10045.  
  10046. !Boolean methodsFor: 'printing'!
  10047. storeOn: aStream 
  10048.     "Refer to the comment in Object|storeOn:."
  10049.  
  10050.     self printOn: aStream! !
  10051.  
  10052. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10053.  
  10054. Boolean class
  10055.     instanceVariableNames: ''!
  10056.  
  10057. !Boolean class methodsFor: 'instance creation'!
  10058. new
  10059.     self error: 'You may not create any more Booleans - this is two-valued logic'! !
  10060. ScriptEditorMorph subclass: #BooleanScriptEditor
  10061.     instanceVariableNames: ''
  10062.     classVariableNames: ''
  10063.     poolDictionaries: ''
  10064.     category: 'Morphic-Scripting-Support'!
  10065. !BooleanScriptEditor commentStamp: 'di 5/22/1998 16:32' prior: 0!
  10066. BooleanScriptEditor class comment:
  10067. 'A ScriptEditor required to hold a Boolean'!
  10068.  
  10069.  
  10070. !BooleanScriptEditor methodsFor: 'all' stamp: 'sw 10/14/97 12:55'!
  10071. storeCodeOn: aStream
  10072.     (submorphs size > 0 and: [submorphs first submorphs size > 0]) ifTrue:
  10073.         [aStream nextPutAll: '(('.
  10074.         super storeCodeOn: aStream.
  10075.         aStream nextPutAll: ') ~~ false)'.
  10076.         ^ self].
  10077.     aStream nextPutAll: ' true '! !
  10078.  
  10079. !BooleanScriptEditor methodsFor: 'all' stamp: 'di 10/17/97 16:32'!
  10080. wantsDroppedMorph: aMorph
  10081.  
  10082.     ^ aMorph isTileLike and: [aMorph resultType ~~ #command]
  10083. ! !
  10084. Morph subclass: #BorderedMorph
  10085.     instanceVariableNames: 'borderWidth borderColor '
  10086.     classVariableNames: ''
  10087.     poolDictionaries: ''
  10088.     category: 'Morphic-Kernel'!
  10089.  
  10090. !BorderedMorph methodsFor: 'initialization' stamp: 'di 6/20/97 11:07'!
  10091. initialize
  10092.     super initialize.
  10093.     borderColor _ Color black.
  10094.     borderWidth _ 2.
  10095. ! !
  10096.  
  10097.  
  10098. !BorderedMorph methodsFor: 'accessing' stamp: 'sw 8/6/97 14:34'!
  10099. borderColor
  10100.     ^ borderColor! !
  10101.  
  10102. !BorderedMorph methodsFor: 'accessing' stamp: 'jm 5/14/1998 11:07'!
  10103. borderColor: colorOrSymbolOrNil
  10104.  
  10105.     borderColor = colorOrSymbolOrNil ifFalse: [
  10106.         borderColor _ colorOrSymbolOrNil.
  10107.         self changed].
  10108. ! !
  10109.  
  10110. !BorderedMorph methodsFor: 'accessing' stamp: 'di 6/20/97 11:24'!
  10111. borderInset
  10112.     self borderColor: #inset! !
  10113.  
  10114. !BorderedMorph methodsFor: 'accessing' stamp: 'di 6/20/97 11:25'!
  10115. borderRaised
  10116.     self borderColor: #raised! !
  10117.  
  10118. !BorderedMorph methodsFor: 'accessing' stamp: 'di 6/20/97 11:09'!
  10119. borderWidth
  10120.     ^ borderWidth! !
  10121.  
  10122. !BorderedMorph methodsFor: 'accessing' stamp: 'sw 11/17/97 14:57'!
  10123. borderWidth: anInteger
  10124.     borderColor ifNil: [borderColor _ Color black].
  10125.     borderWidth _ anInteger max: 0.
  10126.     self changed! !
  10127.  
  10128. !BorderedMorph methodsFor: 'accessing' stamp: 'di 6/20/97 11:19'!
  10129. doesBevels
  10130.     "To return true means that this object can show bevelled borders, and
  10131.     therefore can accept, eg, #raised or #inset as valid borderColors.
  10132.     Must be overridden by subclasses that do not support bevelled borders."
  10133.  
  10134.     ^ true! !
  10135.  
  10136. !BorderedMorph methodsFor: 'accessing' stamp: 'sw 4/13/98 15:22'!
  10137. wearCostume: anotherMorph
  10138.     "Modify the receiver so that it resembles anotherMorph"
  10139.  
  10140.     super wearCostume: anotherMorph.
  10141.     self setBorderWidth: anotherMorph borderWidth borderColor: anotherMorph borderColor
  10142. ! !
  10143.  
  10144.  
  10145. !BorderedMorph methodsFor: 'drawing' stamp: 'di 1/9/98 22:25'!
  10146. drawOn: aCanvas 
  10147.     "Draw a rectangle with a solid, inset, or raised border.
  10148.     Note: the raised border color is generated from the receiver's own color,
  10149.     while the inset border color is generated from the color of its owner.
  10150.     This behavior is visually more consistent. Thanks to Hans-Martin Mosner."
  10151.  
  10152.     | insetColor |
  10153.     borderWidth = 0 ifTrue: [  "no border"
  10154.         aCanvas fillRectangle: bounds color: color.
  10155.         ^ self].
  10156.  
  10157.     borderColor == #raised ifTrue: [
  10158.         ^ aCanvas frameAndFillRectangle: bounds
  10159.             fillColor: color
  10160.             borderWidth: borderWidth
  10161.             topLeftColor: color lighter
  10162.             bottomRightColor: color darker].
  10163.  
  10164.     borderColor == #inset ifTrue: [
  10165.         insetColor _ owner colorForInsets.
  10166.         ^ aCanvas frameAndFillRectangle: bounds
  10167.             fillColor: color
  10168.             borderWidth: borderWidth
  10169.             topLeftColor: insetColor darker
  10170.             bottomRightColor: insetColor lighter].
  10171.  
  10172.     "solid color border"
  10173.     aCanvas frameAndFillRectangle: bounds
  10174.         fillColor: color
  10175.         borderWidth: borderWidth
  10176.         borderColor: borderColor.! !
  10177.  
  10178. !BorderedMorph methodsFor: 'drawing' stamp: 'di 5/17/1998 00:16'!
  10179. drawOnFills: aRectangle
  10180.     ^ (bounds containsRect: aRectangle) and: [self isOpaque]! !
  10181.  
  10182. !BorderedMorph methodsFor: 'drawing' stamp: 'di 5/22/1998 08:45'!
  10183. isOpaque
  10184.     color isTransparent ifTrue: [^ false].
  10185.     borderWidth = 0
  10186.         ifTrue: [^ true]
  10187.         ifFalse: [^ borderColor isColor not or: [borderColor isTransparent not]]! !
  10188.  
  10189.  
  10190. !BorderedMorph methodsFor: 'geometry' stamp: 'di 6/20/97 11:15'!
  10191. innerBounds
  10192.     ^ bounds insetBy: borderWidth! !
  10193.  
  10194.  
  10195. !BorderedMorph methodsFor: 'menu' stamp: 'sw 8/5/97 13:33'!
  10196. addCustomMenuItems: aCustomMenu hand: aHandMorph
  10197.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  10198.     aCustomMenu addList: #(('border color...' changeBorderColor:)
  10199.                         ('border width...' changeBorderWidth:)).
  10200.     self doesBevels ifTrue:
  10201.         [borderColor == #raised ifFalse: [aCustomMenu add: 'raised bevel' action: #borderRaised].
  10202.         borderColor == #inset ifFalse: [aCustomMenu add: 'inset bevel' action: #borderInset]]
  10203. ! !
  10204.  
  10205. !BorderedMorph methodsFor: 'menu' stamp: 'sw 5/13/1998 12:08'!
  10206. changeBorderColor: evt
  10207.     | aHand |
  10208.     aHand _ evt ifNotNil: [evt hand] ifNil: [self primaryHand].
  10209.     aHand changeColorTarget: self selector: #borderColor:.
  10210. ! !
  10211.  
  10212. !BorderedMorph methodsFor: 'menu' stamp: 'sw 5/13/1998 12:11'!
  10213. changeBorderWidth: evt
  10214.     | handle origin aHand |
  10215.     aHand _ evt ifNil: [self primaryHand] ifNotNil: [evt hand].
  10216.     origin _ aHand gridPointRaw.
  10217.     handle _ HandleMorph new forEachPointDo:
  10218.         [:newPoint | handle removeAllMorphs.
  10219.         handle addMorph:
  10220.             (PolygonMorph vertices: (Array with: origin with: newPoint)
  10221.                 color: Color black borderWidth: 1 borderColor: Color black).
  10222.         self borderWidth: (newPoint - origin) r asInteger // 5].
  10223.     aHand attachMorph: handle.
  10224.     handle startStepping! !
  10225.  
  10226. !BorderedMorph methodsFor: 'menu' stamp: 'sw 5/21/1998 15:21'!
  10227. slotNamesAndTypesForBank: aNumber
  10228.     "Return an array of part names and part types for use in a viewer on the receiver's costumee; here we only put the costume-specific parts"
  10229.     ^ aNumber == 2
  10230.         ifTrue: 
  10231.             [#(
  10232.             (color            color        readWrite    getColor                setColor:)
  10233.             (borderWidth         number        readWrite    getBorderWidth    setBorderWidth:)
  10234.             (borderColor            color        readWrite    getBorderColor    setBorderColor:)
  10235.         "(mouseX            number        readOnly    getMouseX            unused)"
  10236.         "(mouseY        number        readOnly    getMouseY            unused)"
  10237. )]
  10238.  
  10239.         ifFalse:
  10240.             [super slotNamesAndTypesForBank: aNumber]
  10241. ! !
  10242.  
  10243.  
  10244. !BorderedMorph methodsFor: 'printing' stamp: 'di 6/20/97 11:20'!
  10245. fullPrintOn: aStream
  10246.     aStream nextPutAll: '('.
  10247.     super fullPrintOn: aStream.
  10248.     aStream nextPutAll: ') setBorderWidth: '; print: borderWidth;
  10249.         nextPutAll: ' borderColor: ' , (self colorString: borderColor)! !
  10250.  
  10251.  
  10252. !BorderedMorph methodsFor: 'private' stamp: 'di 6/20/97 11:21'!
  10253. setBorderWidth: w borderColor: bc
  10254.     self borderWidth: w.
  10255.     self borderColor: bc.! !
  10256.  
  10257. !BorderedMorph methodsFor: 'private' stamp: 'di 6/20/97 11:22'!
  10258. setColor: c borderWidth: w borderColor: bc
  10259.     self color: c.
  10260.     self borderWidth: w.
  10261.     self borderColor: bc.! !
  10262. Morph subclass: #BouncingAtomsMorph
  10263.     instanceVariableNames: 'damageReported infectionHistory transmitInfection '
  10264.     classVariableNames: ''
  10265.     poolDictionaries: ''
  10266.     category: 'Morphic-Demo'!
  10267. !BouncingAtomsMorph commentStamp: 'di 5/22/1998 16:32' prior: 0!
  10268. BouncingAtomsMorph comment:
  10269. 'This morph shows how an ideal gas simulation might work. When it gets step messages, it makes all its atom submorphs move along their velocity vectors, bouncing when they hit a wall. It also exercises the Morphic damage reporting and display architecture. Here are some things to try:
  10270.  
  10271.   1. Resize this morph as the atoms bounce around.
  10272.   2. In an inspector on this morph, evaluate "self addAtoms: 10."
  10273.   3. Try setting quickRedraw to false in invalidRect:. This gives the
  10274.      default damage reporting and incremental redraw. Try it for
  10275.      100 atoms.
  10276.   4. In the drawOn: method of AtomMorph, change drawAsRect to true.
  10277.   5. Create a HeaterCoolerMorph and embed it in the simulation. Extract
  10278.     it and use an inspector on it to evaluate "self velocityDelta: -5", then
  10279.      re-embed it. Note the effect on atoms passing over it.
  10280. '!
  10281.  
  10282.  
  10283. !BouncingAtomsMorph methodsFor: 'all'!
  10284. addAtoms: n
  10285.     "Add a bunch of new atoms."
  10286.  
  10287.     | a |
  10288.     n timesRepeat: [
  10289.         a _ AtomMorph new.
  10290.         a randomPositionIn: bounds maxVelocity: 10.
  10291.         self addMorph: a].
  10292.     self stopStepping.! !
  10293.  
  10294. !BouncingAtomsMorph methodsFor: 'all'!
  10295. addMorphFront: aMorph
  10296.     "Called by the 'embed' meta action. We want non-atoms to go to the back."
  10297.     "Note: A user would not be expected to write this method. However, a sufficiently advanced user (e.g, an e-toy author) might do something equivalent by overridding the drag-n-drop messages when they are implemented."
  10298.  
  10299.     (aMorph isMemberOf: AtomMorph)
  10300.         ifTrue: [super addMorphFront: aMorph]
  10301.         ifFalse: [super addMorphBack: aMorph].! !
  10302.  
  10303. !BouncingAtomsMorph methodsFor: 'all'!
  10304. collisionPairs
  10305.     "Return a list of pairs of colliding atoms, which are assumed to be circles of known radius. This version uses the morph's positions--i.e. the top-left of their bounds rectangles--rather than their centers."
  10306.  
  10307.     | count sortedAtoms radius twoRadii radiiSquared collisions p1 continue j p2 distSquared |
  10308.     count _ submorphs size.
  10309.     sortedAtoms _ submorphs asSortedCollection:
  10310.         [ :m1 :m2 | m1 position x < m2 position x].
  10311.     radius _ 8.
  10312.     twoRadii _ 2 * radius.
  10313.     radiiSquared _ radius squared * 2.
  10314.     collisions _ OrderedCollection new.
  10315.     1 to: count - 1 do: [ :i |
  10316.         m1 _ sortedAtoms at: i.
  10317.         p1 _ m1 position.
  10318.         continue _ (j _ i + 1) <= count.
  10319.         [continue] whileTrue: [
  10320.             m2 _ sortedAtoms at: j.
  10321.             p2 _ m2 position.
  10322.             (p2 x - p1 x) <= twoRadii  ifTrue: [
  10323.                 distSquared _ (p1 x - p2 x) squared + (p1 y - p2 y) squared.
  10324.                 distSquared < radiiSquared ifTrue: [
  10325.                     collisions add: (Array with: m1 with: m2)].
  10326.                 continue _ (j _ j + 1) <= count.
  10327.             ] ifFalse: [
  10328.                 continue _ false.
  10329.             ].
  10330.         ].
  10331.     ].
  10332.     ^ collisions! !
  10333.  
  10334. !BouncingAtomsMorph methodsFor: 'all'!
  10335. drawOn: aCanvas
  10336.     "Clear the damageReported flag when redrawn."
  10337.  
  10338.     super drawOn: aCanvas.
  10339.     damageReported _ false.! !
  10340.  
  10341. !BouncingAtomsMorph methodsFor: 'all' stamp: 'jm 7/30/97 09:45'!
  10342. initialize
  10343.  
  10344.     super initialize.
  10345.     damageReported _ false.
  10346.     self extent: 400@250.
  10347.     self color: (Color r: 0.8 g: 1.0 b: 0.8).
  10348.     infectionHistory _ OrderedCollection new.
  10349.     transmitInfection _ false.
  10350.      self addAtoms: 30.
  10351. ! !
  10352.  
  10353. !BouncingAtomsMorph methodsFor: 'all'!
  10354. invalidRect: damageRect
  10355.     "Try setting 'quickRedraw' to true. This invalidates the entire morph, whose bounds typically subsume all it's submorphs. (However, this code checks that assumption and passes through any damage reports for out-of-bounds submorphs. Note that atoms with super-high velocities do occaisionally shoot through the walls!!) An additional optimization is to only submit only damage report per display cycle by using the damageReported flag, which is reset to false when the morph is drawn."
  10356.  
  10357.     | quickRedraw |
  10358.     quickRedraw _ true.  "false gives the original invalidRect: behavior"
  10359.     (quickRedraw and:
  10360.      [(bounds origin <= damageRect topLeft) and:
  10361.      [damageRect bottomRight <= bounds corner]]) ifTrue: [
  10362.         "can use quick redraw if damage is within my bounds"
  10363.         damageReported ifFalse: [super invalidRect: bounds].  "just report once"
  10364.         damageReported _ true.
  10365.     ] ifFalse: [super invalidRect: damageRect].  "ordinary damage report"! !
  10366.  
  10367. !BouncingAtomsMorph methodsFor: 'all'!
  10368. setGermCount
  10369.  
  10370.     | countString count |
  10371.     countString _ FillInTheBlank
  10372.         request: 'Number of cells?'
  10373.         initialAnswer: self submorphCount printString.
  10374.     countString isEmpty ifTrue: [^ self].
  10375.     count _ Integer readFrom: (ReadStream on: countString).
  10376.     self removeAllMorphs.
  10377.     self addAtoms: count.
  10378. ! !
  10379.  
  10380. !BouncingAtomsMorph methodsFor: 'all'!
  10381. startInfection
  10382.  
  10383.     self submorphsDo: [:m | m infected: false].
  10384.     self firstSubmorph infected: true.
  10385.     infectionHistory _ OrderedCollection new: 500.
  10386.     transmitInfection _ true.
  10387.     self startStepping.
  10388. ! !
  10389.  
  10390. !BouncingAtomsMorph methodsFor: 'all'!
  10391. step
  10392.     "Bounce those atoms!!"
  10393.  
  10394.     | r |
  10395.     r _ bounds origin corner: (bounds corner - (8@8)).
  10396.     self submorphsDo: [ :m |
  10397.         (m isMemberOf: AtomMorph) ifTrue: [m bounceIn: r]].
  10398.     transmitInfection ifTrue: [self transmitInfection].
  10399. ! !
  10400.  
  10401. !BouncingAtomsMorph methodsFor: 'all'!
  10402. stepTime
  10403.     "As fast as possible."
  10404.  
  10405.     ^ 0! !
  10406.  
  10407. !BouncingAtomsMorph methodsFor: 'all'!
  10408. transmitInfection
  10409.  
  10410.     | infected count graph |
  10411.     self collisionPairs do: [:pair |
  10412.         infected _ false.
  10413.         pair do: [:atom | atom infected ifTrue: [infected _ true]].
  10414.         infected
  10415.             ifTrue: [pair do: [:atom | atom infected: true]]].
  10416.  
  10417.     count _ 0.
  10418.     self submorphsDo: [:m | m infected ifTrue: [count _ count + 1]].
  10419.     infectionHistory addLast: count.
  10420.     count = submorphs size ifTrue: [
  10421.         "done!! place a graph of the infection history in the world"
  10422.         graph _ GraphMorph new data: infectionHistory.
  10423.         graph position: bounds topRight + (10@0).
  10424.         graph extent: (((infectionHistory size * 3) + (2 * graph borderWidth))@count).
  10425.         self world addMorph: graph.
  10426.         graph changed.
  10427.         transmitInfection _ false.
  10428.         self stopStepping].
  10429. ! !
  10430. Object subclass: #BraceConstructor
  10431.     instanceVariableNames: 'elements initIndex subBraceSize constructor decompiler '
  10432.     classVariableNames: ''
  10433.     poolDictionaries: ''
  10434.     category: 'System-Compiler'!
  10435.  
  10436. !BraceConstructor methodsFor: 'constructing'!
  10437. codeBrace: numElements fromBytes: aDecompiler withConstructor: aConstructor
  10438.     "Decompile.  Consume at least a Pop and usually several stores into variables
  10439.      or braces.  See BraceNode<formBrace for details."
  10440.  
  10441.     decompiler _ aDecompiler.
  10442.     constructor _ aConstructor.
  10443.     elements _ Array new: (initIndex _ numElements).
  10444.     [decompiler interpretNextInstructionFor: self.
  10445.      initIndex = 0]
  10446.         whileFalse: [].
  10447.     ^constructor codeBrace: elements! !
  10448.  
  10449.  
  10450. !BraceConstructor methodsFor: 'instruction decoding'!
  10451. doPop
  10452.     "Decompile."! !
  10453.  
  10454. !BraceConstructor methodsFor: 'instruction decoding'!
  10455. popIntoLiteralVariable: association
  10456.     "Decompile."
  10457.  
  10458.     elements at: initIndex put: (constructor codeAnyLitInd: association).
  10459.     initIndex _ initIndex - 1! !
  10460.  
  10461. !BraceConstructor methodsFor: 'instruction decoding'!
  10462. popIntoReceiverVariable: offset
  10463.     "Decompile."
  10464.  
  10465.     elements at: initIndex put: (constructor codeInst: offset).
  10466.     initIndex _ initIndex - 1! !
  10467.  
  10468. !BraceConstructor methodsFor: 'instruction decoding'!
  10469. popIntoTemporaryVariable: offset
  10470.     "Decompile."
  10471.  
  10472.     elements at: initIndex put: (decompiler tempAt: offset).
  10473.     initIndex _ initIndex - 1! !
  10474.  
  10475. !BraceConstructor methodsFor: 'instruction decoding'!
  10476. pushConstant: value
  10477.  
  10478.     subBraceSize _ value! !
  10479.  
  10480. !BraceConstructor methodsFor: 'instruction decoding'!
  10481. send: selector super: superFlag numArgs: numArgs
  10482.  
  10483.     selector == #toBraceStack:
  10484.         ifFalse: [self error: 'Malformed brace-variable code'].
  10485.     elements at: initIndex put:
  10486.         (BraceConstructor new
  10487.             codeBrace: subBraceSize
  10488.             fromBytes: decompiler
  10489.             withConstructor: constructor).
  10490.     initIndex _ initIndex - 1! !
  10491.  
  10492. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10493.  
  10494. BraceConstructor class
  10495.     instanceVariableNames: ''!
  10496.  
  10497. !BraceConstructor class methodsFor: 'examples'!
  10498. example
  10499.     "Test the {a. b. c} syntax.  For more examples, see SequenceableCollection-casing
  10500.      and Dictionary-casing."
  10501.  
  10502.     | a b c d e x y |
  10503.     x _ {1. {2. 3}. 4}.
  10504.     {a. {b. c}. d. e} _ x, {5}, {}.
  10505.     y _ {a} _ {0}.
  10506.     {} _ {}.
  10507.     ^{e. d. c. b. a + 1. y first} as: Set
  10508.  
  10509. "BraceNode example"
  10510. "Smalltalk garbageCollect.
  10511.  Time millisecondsToRun: [20 timesRepeat: [BraceNode example]] 1097 2452"! !
  10512. ParseNode subclass: #BraceNode
  10513.     instanceVariableNames: 'elements sourceLocations collClassNode nElementsNode fromBraceStackNode toBraceStackNode withNode '
  10514.     classVariableNames: ''
  10515.     poolDictionaries: ''
  10516.     category: 'System-Compiler'!
  10517.  
  10518. !BraceNode methodsFor: 'initialize-release'!
  10519. collClass: aParseNode
  10520.  
  10521.     collClassNode _ aParseNode! !
  10522.  
  10523. !BraceNode methodsFor: 'initialize-release'!
  10524. elements: collection
  10525.     "Decompile."
  10526.  
  10527.     elements _ collection! !
  10528.  
  10529. !BraceNode methodsFor: 'initialize-release'!
  10530. elements: collection sourceLocations: locations
  10531.     "Compile."
  10532.  
  10533.     elements _ collection.
  10534.     sourceLocations _ locations! !
  10535.  
  10536.  
  10537. !BraceNode methodsFor: 'testing'!
  10538. assignmentCheck: encoder at: location
  10539.  
  10540.     | loc |
  10541.     elements do:
  10542.         [:element |
  10543.         (loc _ element assignmentCheck: encoder at: location) >= 0 ifTrue: [^loc]].
  10544.     ^-1! !
  10545.  
  10546. !BraceNode methodsFor: 'testing'!
  10547. blockAssociationCheck: encoder
  10548.     "If all elements are MessageNodes of the form [block]->[block], and there is at
  10549.      least one element, answer true.
  10550.      Otherwise, notify encoder of an error."
  10551.  
  10552.     elements size = 0
  10553.         ifTrue: [^encoder notify: 'At least one case required'].
  10554.     elements with: sourceLocations do:
  10555.             [:x :loc |
  10556.             (x     isMessage: #->
  10557.                 receiver:
  10558.                     [:rcvr |
  10559.                     (rcvr isKindOf: BlockNode) and: [rcvr numberOfArguments = 0]]
  10560.                 arguments:
  10561.                     [:arg |
  10562.                     (arg isKindOf: BlockNode) and: [arg numberOfArguments = 0]])
  10563.               ifFalse:
  10564.                 [^encoder notify: 'Association between 0-argument blocks required' at: loc]].
  10565.     ^true! !
  10566.  
  10567. !BraceNode methodsFor: 'testing'!
  10568. numElements
  10569.  
  10570.     ^ elements size! !
  10571.  
  10572.  
  10573. !BraceNode methodsFor: 'code generation'!
  10574. emitForValue: stack on: aStream
  10575.     "elem1, ..., elemN, collectionClass, N, fromBraceStack:"
  10576.  
  10577.     elements do: [:element | element emitForValue: stack on: aStream].
  10578.     collClassNode emitForValue: stack on: aStream.
  10579.     nElementsNode emitForValue: stack on: aStream.
  10580.     fromBraceStackNode emit: stack args: 1 on: aStream.
  10581.     stack pop: elements size! !
  10582.  
  10583. !BraceNode methodsFor: 'code generation'!
  10584. emitStore: stack on: aStream
  10585.  
  10586.     aStream nextPut: Dup. stack push: 1.
  10587.     self emitStorePop: stack on: aStream! !
  10588.  
  10589. !BraceNode methodsFor: 'code generation'!
  10590. emitStorePop: stack on: aStream
  10591.     "N, toBraceStack:, pop, pop elemN, ..., pop elem1"
  10592.  
  10593.     nElementsNode emitForValue: stack on: aStream.
  10594.     toBraceStackNode emit: stack args: 1 on: aStream.
  10595.     stack push: elements size.
  10596.     aStream nextPut: Pop. stack pop: 1.
  10597.     elements reverseDo: [:element | element emitStorePop: stack on: aStream]! !
  10598.  
  10599. !BraceNode methodsFor: 'code generation'!
  10600. sizeForStore: encoder
  10601.  
  10602.     ^1 + (self sizeForStorePop: encoder)! !
  10603.  
  10604. !BraceNode methodsFor: 'code generation'!
  10605. sizeForStorePop: encoder
  10606.     "N, toBraceStack:, pop, pop elemN, ..., pop elem1"
  10607.  
  10608.     nElementsNode _ encoder encodeLiteral: elements size.
  10609.     toBraceStackNode _ encoder encodeSelector: #toBraceStack:.
  10610.     ^elements inject:
  10611.         (nElementsNode sizeForValue: encoder) +
  10612.         (toBraceStackNode size: encoder args: 1 super: false) + 1 into:
  10613.             [:subTotal :element |
  10614.              subTotal + (element sizeForStorePop: encoder)]! !
  10615.  
  10616. !BraceNode methodsFor: 'code generation'!
  10617. sizeForValue: encoder
  10618.     "elem1, ..., elemN, collectionClass, N, fromBraceStack:"
  10619.  
  10620.     nElementsNode _ encoder encodeLiteral: elements size.
  10621.     collClassNode isNil ifTrue:
  10622.         [collClassNode _ encoder encodeVariable: #Array].
  10623.     fromBraceStackNode _ encoder encodeSelector: #fromBraceStack:.
  10624.     ^elements inject:
  10625.         (nElementsNode sizeForValue: encoder) +
  10626.         (collClassNode sizeForValue: encoder) +
  10627.         (fromBraceStackNode size: encoder args: 1 super: false)
  10628.      into:
  10629.         [:subTotal :element |
  10630.          subTotal + (element sizeForValue: encoder)]! !
  10631.  
  10632.  
  10633. !BraceNode methodsFor: 'enumerating'!
  10634. casesForwardDo: aBlock
  10635.     "For each case in forward order, evaluate aBlock with three arguments:
  10636.      the key block, the value block, and whether it is the last case."
  10637.  
  10638.     | numCases case |
  10639.     1 to: (numCases _ elements size) do:
  10640.         [:i |
  10641.         case _ elements at: i.
  10642.         aBlock value: case receiver value: case arguments first value: i=numCases]! !
  10643.  
  10644. !BraceNode methodsFor: 'enumerating'!
  10645. casesReverseDo: aBlock
  10646.     "For each case in reverse order, evaluate aBlock with three arguments:
  10647.      the key block, the value block, and whether it is the last case."
  10648.  
  10649.     | numCases case |
  10650.     (numCases _ elements size) to: 1 by: -1 do:
  10651.         [:i |
  10652.         case _ elements at: i.
  10653.         aBlock value: case receiver value: case arguments first value: i=numCases]! !
  10654.  
  10655. !BraceNode methodsFor: 'enumerating'!
  10656. do: aBlock
  10657.     "For each element in order, evaluate aBlock with two arguments: the element,
  10658.      and whether it is the last element."
  10659.  
  10660.     | numElements |
  10661.     1 to: (numElements _ elements size) do:
  10662.         [:i | aBlock value: (elements at: i) value: i=numElements]! !
  10663.  
  10664. !BraceNode methodsFor: 'enumerating'!
  10665. reverseDo: aBlock
  10666.     "For each element in reverse order, evaluate aBlock with two arguments: the element,
  10667.      and whether it is the last element."
  10668.  
  10669.     | numElements |
  10670.     (numElements _ elements size) to: 1 by: -1 do:
  10671.         [:i | aBlock value: (elements at: i) value: i=numElements]! !
  10672.  
  10673.  
  10674. !BraceNode methodsFor: 'printing'!
  10675. printOn: aStream indent: level
  10676.  
  10677.     | shown |
  10678.     aStream nextPut: ${.
  10679.     shown _ elements size.
  10680.     1 to: shown do: 
  10681.         [:i | 
  10682.         (elements at: i) printOn: aStream indent: level.
  10683.         i < shown ifTrue: [aStream nextPut: $.; space]].
  10684.     aStream nextPut: $}! !
  10685.  
  10686. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  10687.  
  10688. BraceNode class
  10689.     instanceVariableNames: ''!
  10690.  
  10691. !BraceNode class methodsFor: 'examples'!
  10692. example
  10693.     "Test the {a. b. c} syntax."
  10694.  
  10695.     | a b c d e x y |
  10696.     x _ {1. {2. 3}. 4}.
  10697.     {a. {b. c}. d. e} _ x, {5}, {}.
  10698.     y _ {a} _ {0}.
  10699.     {} _ {}.
  10700.     ^{e. d. c. b. a + 1. y first} as: Set
  10701.  
  10702. "BraceNode example"
  10703. "Smalltalk garbageCollect.
  10704.  Time millisecondsToRun: [20 timesRepeat: [BraceNode example]] 1097 2452"! !
  10705. StringHolder subclass: #Browser
  10706.     instanceVariableNames: 'systemOrganizer classOrganizer metaClassOrganizer systemCategoryListIndex classListIndex messageCategoryListIndex messageListIndex editSelection metaClassIndicated '
  10707.     classVariableNames: 'RecentClasses '
  10708.     poolDictionaries: ''
  10709.     category: 'Interface-Browser'!
  10710. !Browser commentStamp: 'di 5/22/1998 16:32' prior: 0!
  10711. Browser comment:
  10712. 'I represent a query path into the class descriptions, the software of the system.'!
  10713.  
  10714.  
  10715. !Browser methodsFor: 'initialize-release'!
  10716. browserWindowActivated
  10717.     "Called when a window whose model is the receiver is reactivated, giving the receiver an opportunity to take steps if it wishes.  The default is to do nothing.  8/5/96 sw"! !
  10718.  
  10719. !Browser methodsFor: 'initialize-release' stamp: 'tk 4/8/98 15:22'!
  10720. buildClassSwitchView
  10721.  
  10722.     | aSwitchView |
  10723.     aSwitchView _ PluggableButtonView
  10724.         on: self
  10725.         getState: #classMessagesIndicated
  10726.         action: #indicateClassMessages.
  10727.     aSwitchView
  10728.         label: 'class';
  10729.         window: (0@0 extent: 15@8);
  10730.         askBeforeChanging: true.
  10731.     ^ aSwitchView
  10732. ! !
  10733.  
  10734. !Browser methodsFor: 'initialize-release' stamp: 'tk 4/8/98 16:10'!
  10735. buildCommentSwitchView
  10736.  
  10737.     | aSwitchView |
  10738.     aSwitchView _ PluggableButtonView
  10739.         on: self
  10740.         getState: #classCommentIndicated
  10741.         action: #editComment.
  10742.     aSwitchView
  10743.         label: '?' asText allBold asParagraph;
  10744.         borderWidthLeft: 0 right: 1 top: 0 bottom: 0;    
  10745.         window: (0@0 extent: 10@8);
  10746.         askBeforeChanging: true.
  10747.     ^ aSwitchView
  10748. ! !
  10749.  
  10750. !Browser methodsFor: 'initialize-release' stamp: 'tk 4/8/98 16:11'!
  10751. buildInstanceClassSwitchView
  10752.     | aView aSwitchView instSwitchView comSwitchView |
  10753.  
  10754.     aView _ View new model: self.
  10755.     aView window: (0 @ 0 extent: 50 @ 8).
  10756.     instSwitchView _ self buildInstanceSwitchView.
  10757.     aView addSubView: instSwitchView.
  10758.     comSwitchView _ self buildCommentSwitchView.
  10759.     aView addSubView: comSwitchView toRightOf: instSwitchView.
  10760.     aSwitchView _ self buildClassSwitchView.
  10761.     aView addSubView: aSwitchView toRightOf: comSwitchView.
  10762.     ^aView! !
  10763.  
  10764. !Browser methodsFor: 'initialize-release' stamp: 'tk 4/8/98 16:10'!
  10765. buildInstanceSwitchView
  10766.  
  10767.     | aSwitchView |
  10768.     aSwitchView _ PluggableButtonView
  10769.         on: self
  10770.         getState: #instanceMessagesIndicated
  10771.         action: #indicateInstanceMessages.
  10772.     aSwitchView
  10773.         label: 'instance';
  10774.         borderWidthLeft: 0 right: 1 top: 0 bottom: 0;    
  10775.         window: (0@0 extent: 25@8);
  10776.         askBeforeChanging: true.
  10777.     ^ aSwitchView
  10778. ! !
  10779.  
  10780. !Browser methodsFor: 'initialize-release' stamp: 'di 5/16/1998 15:04'!
  10781. buildMorphicSwitches
  10782.  
  10783.     | instanceSwitch commentSwitch classSwitch row |
  10784.     instanceSwitch _ PluggableButtonMorph
  10785.         on: self
  10786.         getState: #instanceMessagesIndicated
  10787.         action: #indicateInstanceMessages.
  10788.     instanceSwitch
  10789.         label: 'instance';
  10790.         askBeforeChanging: true.
  10791.     commentSwitch _ PluggableButtonMorph
  10792.         on: self
  10793.         getState: #classCommentIndicated
  10794.         action: #editComment.
  10795.     commentSwitch
  10796.         label: '?' asText allBold asParagraph;
  10797.         askBeforeChanging: true.
  10798.     classSwitch _ PluggableButtonMorph
  10799.         on: self
  10800.         getState: #classMessagesIndicated
  10801.         action: #indicateClassMessages.
  10802.     classSwitch
  10803.         label: 'class';
  10804.         askBeforeChanging: true.
  10805.     row _ AlignmentMorph newRow
  10806.         hResizing: #spaceFill;
  10807.         vResizing: #spaceFill;
  10808.         inset: 0;
  10809.         borderColor: Color transparent;
  10810.         addMorphBack: instanceSwitch;
  10811.         addMorphBack: commentSwitch;
  10812.         addMorphBack: classSwitch.
  10813.     ^ row
  10814. ! !
  10815.  
  10816. !Browser methodsFor: 'initialize-release'!
  10817. defaultBackgroundColor
  10818.     ^ #lightGreen! !
  10819.  
  10820. !Browser methodsFor: 'initialize-release' stamp: 'di 5/16/1998 17:21'!
  10821. openAsMorphClassEditing: editString
  10822.     "Create a pluggable version a Browser on just a single class."
  10823.     | window codePane |
  10824.     window _ (SystemWindow labelled: 'later') model: self.
  10825.  
  10826.     window addMorph: (PluggableListMorph on: self list: #classListSingleton
  10827.             selected: #indexIsOne changeSelected: #indexIsOne:
  10828.             menu: #classListMenu:)
  10829.         frame: (0@0 extent: 0.5@0.06).
  10830.     window addMorph: self buildMorphicSwitches
  10831.         frame: (0.5@0 extent: 0.5@0.06).
  10832.     window addMorph: (PluggableListMorph on: self list: #messageCategoryList
  10833.             selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex:
  10834.             menu: #messageCategoryMenu:)
  10835.         frame: (0@0.06 extent: 0.5@0.30).
  10836.     window addMorph: (PluggableListMorph on: self list: #messageList
  10837.             selected: #messageListIndex changeSelected: #messageListIndex:
  10838.             menu: #messageListMenu:shifted:)
  10839.         frame: (0.5@0.06 extent: 0.5@0.30).
  10840.  
  10841.     codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying:
  10842.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  10843.     editString ifNotNil: [codePane editString: editString.
  10844.                     codePane hasUnacceptedEdits: true].
  10845.     window addMorph: codePane
  10846.         frame: (0@0.36 corner: 1@1).
  10847.  
  10848.     ^ window! !
  10849.  
  10850. !Browser methodsFor: 'initialize-release' stamp: 'di 5/16/1998 16:08'!
  10851. openAsMorphEditing: editString
  10852.     "Create a pluggable version of all the views for a Browser, including views and controllers."
  10853.     | window codePane |
  10854.     window _ (SystemWindow labelled: 'later') model: self.
  10855.  
  10856.     window addMorph: (PluggableListMorph on: self list: #systemCategoryList
  10857.             selected: #systemCategoryListIndex changeSelected: #systemCategoryListIndex:
  10858.             menu: #systemCategoryMenu:)
  10859.         frame: (0@0 extent: 0.25@0.4).
  10860.     window addMorph: (PluggableListMorph on: self list: #classList
  10861.             selected: #classListIndex changeSelected: #classListIndex:
  10862.             menu: #classListMenu:)
  10863.         frame: (0.25@0 extent: 0.25@0.3).
  10864.     window addMorph: self buildMorphicSwitches
  10865.         frame: (0.25@0.3 extent: 0.25@0.1).
  10866.     window addMorph: (PluggableListMorph on: self list: #messageCategoryList
  10867.             selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex:
  10868.             menu: #messageCategoryMenu:)
  10869.         frame: (0.5@0 extent: 0.25@0.4).
  10870.     window addMorph: (PluggableListMorph on: self list: #messageList
  10871.             selected: #messageListIndex changeSelected: #messageListIndex:
  10872.             menu: #messageListMenu:shifted:)
  10873.         frame: (0.75@0 extent: 0.25@0.4).
  10874.  
  10875.     codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying:
  10876.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  10877.     editString ifNotNil: [codePane editString: editString.
  10878.                     codePane hasUnacceptedEdits: true].
  10879.     window addMorph: codePane
  10880.         frame: (0@0.4 corner: 1@1).
  10881.  
  10882.     ^ window! !
  10883.  
  10884. !Browser methodsFor: 'initialize-release' stamp: 'di 5/6/1998 21:36'!
  10885. openAsMorphMessageEditing: editString
  10886.     "Create a pluggable version a Browser on just a messageCategory."
  10887.     | window codePane |
  10888.     window _ (SystemWindow labelled: 'later') model: self.
  10889.  
  10890.     window addMorph: (PluggableListMorph on: self list: #messageListSingleton
  10891.             selected: #indexIsOne changeSelected: #indexIsOne:
  10892.             menu: #messageListMenu:shifted:)
  10893.         frame: (0@0 extent: 1.0@0.06).
  10894.  
  10895.     codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying:
  10896.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  10897.     editString ifNotNil: [codePane editString: editString.
  10898.                     codePane hasUnacceptedEdits: true].
  10899.     window addMorph: codePane
  10900.         frame: (0@0.06 corner: 1@1).
  10901.  
  10902.     ^ window! !
  10903.  
  10904. !Browser methodsFor: 'initialize-release' stamp: 'di 5/6/1998 21:36'!
  10905. openAsMorphMsgCatEditing: editString
  10906.     "Create a pluggable version a Browser on just a messageCategory."
  10907.     | window codePane |
  10908.     window _ (SystemWindow labelled: 'later') model: self.
  10909.  
  10910.     window addMorph: (PluggableListMorph on: self list: #messageCatListSingleton
  10911.             selected: #indexIsOne changeSelected: #indexIsOne:
  10912.             menu: #messageCategoryMenu:)
  10913.         frame: (0@0 extent: 1.0@0.06).
  10914.     window addMorph: (PluggableListMorph on: self list: #messageList
  10915.             selected: #messageListIndex changeSelected: #messageListIndex:
  10916.             menu: #messageListMenu:shifted:)
  10917.         frame: (0@0.06 extent: 1.0@0.30).
  10918.  
  10919.     codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying:
  10920.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  10921.     editString ifNotNil: [codePane editString: editString.
  10922.                     codePane hasUnacceptedEdits: true].
  10923.     window addMorph: codePane
  10924.         frame: (0@0.36 corner: 1@1).
  10925.  
  10926.     ^ window! !
  10927.  
  10928. !Browser methodsFor: 'initialize-release' stamp: 'di 5/16/1998 17:19'!
  10929. openAsMorphSysCatEditing: editString
  10930.     "Create a pluggable version of all the views for a Browser, including views and controllers."
  10931.     | window codePane |
  10932.     window _ (SystemWindow labelled: 'later') model: self.
  10933.  
  10934.     window addMorph: (PluggableListMorph on: self list: #systemCategorySingleton
  10935.             selected: #indexIsOne changeSelected: #indexIsOne:
  10936.             menu: #systemCategoryMenu:)
  10937.         frame: (0@0 extent: 1.0@0.06).
  10938.     window addMorph: (PluggableListMorph on: self list: #classList
  10939.             selected: #classListIndex changeSelected: #classListIndex:
  10940.             menu: #classListMenu:)
  10941.         frame: (0@0.06 extent: 0.3333@0.24).
  10942.     window addMorph: self buildMorphicSwitches
  10943.         frame: (0@0.3 extent: 0.3333@0.06).
  10944.     window addMorph: (PluggableListMorph on: self list: #messageCategoryList
  10945.             selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex:
  10946.             menu: #messageCategoryMenu:)
  10947.         frame: (0.3333@0.06 extent: 0.3333@0.30).
  10948.     window addMorph: (PluggableListMorph on: self list: #messageList
  10949.             selected: #messageListIndex changeSelected: #messageListIndex:
  10950.             menu: #messageListMenu:shifted:)
  10951.         frame: (0.6666@0.06 extent: 0.3333@0.30).
  10952.  
  10953.     codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying:
  10954.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  10955.     editString ifNotNil: [codePane editString: editString.
  10956.                     codePane hasUnacceptedEdits: true].
  10957.     window addMorph: codePane
  10958.         frame: (0@0.36 corner: 1@1).
  10959.  
  10960.     ^ window! !
  10961.  
  10962. !Browser methodsFor: 'initialize-release' stamp: 'di 5/16/1998 17:07'!
  10963. openEditString: aString
  10964.     "Create a pluggable version of all the views for a Browser, including views and controllers."
  10965.     | systemCategoryListView classListView 
  10966.     messageCategoryListView messageListView browserCodeView topView switchView |
  10967.  
  10968.     World ifNotNil: [^ self openAsMorphEditing: aString].
  10969.     Sensor leftShiftDown ifTrue: [^ self openAsMorphEditing: aString "testing"].
  10970.  
  10971.     topView _ (StandardSystemView new) model: self.
  10972.     topView borderWidth: 1.
  10973.         "label and minSize taken care of by caller"
  10974.  
  10975.     systemCategoryListView _ PluggableListView on: self
  10976.         list: #systemCategoryList
  10977.         selected: #systemCategoryListIndex
  10978.         changeSelected: #systemCategoryListIndex:
  10979.         menu: #systemCategoryMenu:.
  10980.     systemCategoryListView window: (0 @ 0 extent: 50 @ 70).
  10981.     topView addSubView: systemCategoryListView.
  10982.  
  10983.     classListView _ PluggableListView on: self
  10984.         list: #classList
  10985.         selected: #classListIndex
  10986.         changeSelected: #classListIndex:
  10987.         menu: #classListMenu:.
  10988.     classListView window: (0 @ 0 extent: 50 @ 62).
  10989.     topView addSubView: classListView toRightOf: systemCategoryListView.
  10990.  
  10991.     switchView _ self buildInstanceClassSwitchView.
  10992.     switchView borderWidth: 1.
  10993.     topView addSubView: switchView below: classListView.
  10994.  
  10995.     messageCategoryListView _ PluggableListView on: self
  10996.         list: #messageCategoryList
  10997.         selected: #messageCategoryListIndex
  10998.         changeSelected: #messageCategoryListIndex:
  10999.         menu: #messageCategoryMenu:.
  11000.     messageCategoryListView window: (0 @ 0 extent: 50 @ 70).
  11001.     topView addSubView: messageCategoryListView toRightOf: classListView.
  11002.  
  11003.     messageListView _ PluggableListView on: self
  11004.         list: #messageList
  11005.         selected: #messageListIndex
  11006.         changeSelected: #messageListIndex:
  11007.         menu: #messageListMenu:shifted:
  11008.         keystroke: #messageListKey:from:.
  11009.     messageListView window: (0 @ 0 extent: 50 @ 70).
  11010.     topView addSubView: messageListView toRightOf: messageCategoryListView.
  11011.  
  11012.     browserCodeView _ PluggableTextView on: self 
  11013.             text: #contents accept: #contents:notifying:
  11014.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  11015.     browserCodeView window: (0@0 extent: 200@110).
  11016.     topView addSubView: browserCodeView below: systemCategoryListView.
  11017.     aString ifNotNil: [browserCodeView editString: aString.
  11018.             browserCodeView hasUnacceptedEdits: true].
  11019.     ^ topView
  11020. ! !
  11021.  
  11022. !Browser methodsFor: 'initialize-release' stamp: 'tk 5/6/1998 21:25'!
  11023. openMessageCatEditString: aString
  11024.     "Create a pluggable version of the views for a Browser that just shows one message category."
  11025.     | messageCategoryListView messageListView browserCodeView topView |
  11026.  
  11027.     World ifNotNil: [^ self openAsMorphMsgCatEditing: aString].
  11028.  
  11029.     topView _ (StandardSystemView new) model: self.
  11030.     topView borderWidth: 1.
  11031.         "label and minSize taken care of by caller"
  11032.  
  11033.     messageCategoryListView _ PluggableListView on: self
  11034.         list: #messageCatListSingleton
  11035.         selected: #indexIsOne 
  11036.         changeSelected: #indexIsOne:
  11037.         menu: #messageCategoryMenu:.
  11038.     messageCategoryListView window: (0 @ 0 extent: 200 @ 12).
  11039.     topView addSubView: messageCategoryListView.
  11040.  
  11041.     messageListView _ PluggableListView on: self
  11042.         list: #messageList
  11043.         selected: #messageListIndex
  11044.         changeSelected: #messageListIndex:
  11045.         menu: #messageListMenu:shifted:
  11046.         keystroke: #messageListKey:from:.
  11047.     messageListView window: (0 @ 0 extent: 200 @ 70).
  11048.     topView addSubView: messageListView below: messageCategoryListView.
  11049.  
  11050.     browserCodeView _ PluggableTextView on: self 
  11051.             text: #contents accept: #contents:notifying:
  11052.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  11053.     browserCodeView window: (0@0 extent: 200@(200-12-70)).
  11054.     topView addSubView: browserCodeView below: messageListView.
  11055.     aString ifNotNil: [browserCodeView editString: aString.
  11056.             browserCodeView hasUnacceptedEdits: true].
  11057.     ^ topView
  11058. ! !
  11059.  
  11060. !Browser methodsFor: 'initialize-release' stamp: 'tk 5/6/1998 21:27'!
  11061. openMessageEditString: aString
  11062.     "Create a pluggable version of the views for a Browser that just shows one message."
  11063.     | messageListView browserCodeView topView |
  11064.  
  11065.     World ifNotNil: [^ self openAsMorphMessageEditing: aString].
  11066.  
  11067.     topView _ (StandardSystemView new) model: self.
  11068.     topView borderWidth: 1.
  11069.         "label and minSize taken care of by caller"
  11070.  
  11071.     messageListView _ PluggableListView on: self
  11072.         list: #messageListSingleton
  11073.         selected: #indexIsOne 
  11074.         changeSelected: #indexIsOne:
  11075.         menu: #messageListMenu:shifted:.
  11076.     messageListView window: (0 @ 0 extent: 200 @ 12).
  11077.     topView addSubView: messageListView.
  11078.  
  11079.     browserCodeView _ PluggableTextView on: self 
  11080.             text: #contents accept: #contents:notifying:
  11081.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  11082.     browserCodeView window: (0@0 extent: 200@(200-12)).
  11083.     topView addSubView: browserCodeView below: messageListView.
  11084.     aString ifNotNil: [browserCodeView editString: aString.
  11085.             browserCodeView hasUnacceptedEdits: true].
  11086.     ^ topView
  11087. ! !
  11088.  
  11089. !Browser methodsFor: 'initialize-release' stamp: 'tk 5/6/1998 21:25'!
  11090. openOnClassWithEditString: aString
  11091.     "Create a pluggable version of all the views for a Browser, including views and controllers."
  11092.     | classListView messageCategoryListView messageListView browserCodeView topView switchView |
  11093.  
  11094.     World ifNotNil: [^ self openAsMorphClassEditing: aString].
  11095.  
  11096.     topView _ (StandardSystemView new) model: self.
  11097.     topView borderWidth: 1.
  11098.         "label and minSize taken care of by caller"
  11099.  
  11100.     classListView _ PluggableListView on: self
  11101.         list: #classListSingleton
  11102.         selected: #indexIsOne 
  11103.         changeSelected: #indexIsOne:
  11104.         menu: #classListMenu:.
  11105.     classListView window: (0 @ 0 extent: 100 @ 12).
  11106.     topView addSubView: classListView.
  11107.  
  11108.     messageCategoryListView _ PluggableListView on: self
  11109.         list: #messageCategoryList
  11110.         selected: #messageCategoryListIndex
  11111.         changeSelected: #messageCategoryListIndex:
  11112.         menu: #messageCategoryMenu:.
  11113.     messageCategoryListView window: (0 @ 0 extent: 100 @ 70).
  11114.     topView addSubView: messageCategoryListView below: classListView.
  11115.  
  11116.     messageListView _ PluggableListView on: self
  11117.         list: #messageList
  11118.         selected: #messageListIndex
  11119.         changeSelected: #messageListIndex:
  11120.         menu: #messageListMenu:shifted:
  11121.         keystroke: #messageListKey:from:.
  11122.     messageListView window: (0 @ 0 extent: 100 @ 70).
  11123.     topView addSubView: messageListView toRightOf: messageCategoryListView.
  11124.  
  11125.     switchView _ self buildInstanceClassSwitchView.
  11126.     switchView borderWidth: 1.
  11127.     switchView 
  11128.         window: switchView window 
  11129.         viewport: (classListView viewport topRight 
  11130.                     corner: messageListView viewport topRight).
  11131.     topView addSubView: switchView toRightOf: classListView.
  11132.  
  11133.     browserCodeView _ PluggableTextView on: self 
  11134.             text: #contents accept: #contents:notifying:
  11135.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  11136.     browserCodeView window: (0@0 extent: 200@(200-12-70)).
  11137.     topView addSubView: browserCodeView below: messageCategoryListView.
  11138.     aString ifNotNil: [browserCodeView editString: aString.
  11139.             browserCodeView hasUnacceptedEdits: true].
  11140.     ^ topView
  11141. ! !
  11142.  
  11143. !Browser methodsFor: 'initialize-release' stamp: 'di 5/8/1998 22:31'!
  11144. openSystemCatEditString: aString
  11145.     "Create a pluggable version of all the views for a Browser, including views and controllers.  The top list view is of the currently selected system class category--a single item list."
  11146.     | systemCategoryListView classListView messageCategoryListView messageListView browserCodeView topView switchView |
  11147.  
  11148.     World ifNotNil: [^ self openAsMorphSysCatEditing: aString].
  11149.  
  11150.     topView _ (StandardSystemView new) model: self.
  11151.     topView borderWidth: 1.
  11152.         "label and minSize taken care of by caller"
  11153.  
  11154.     systemCategoryListView _ PluggableListView on: self
  11155.         list: #systemCategorySingleton
  11156.         selected: #indexIsOne 
  11157.         changeSelected: #indexIsOne:
  11158.         menu: #systemCategoryMenu:.
  11159.     systemCategoryListView window: (0 @ 0 extent: 200 @ 12).
  11160.     topView addSubView: systemCategoryListView.
  11161.  
  11162.     classListView _ PluggableListView on: self
  11163.         list: #classList
  11164.         selected: #classListIndex
  11165.         changeSelected: #classListIndex:
  11166.         menu: #classListMenu:.
  11167.     classListView window: (0 @ 0 extent: 67 @ 62).
  11168.     topView addSubView: classListView below: systemCategoryListView.
  11169.  
  11170.     messageCategoryListView _ PluggableListView on: self
  11171.         list: #messageCategoryList
  11172.         selected: #messageCategoryListIndex
  11173.         changeSelected: #messageCategoryListIndex:
  11174.         menu: #messageCategoryMenu:.
  11175.     messageCategoryListView window: (0 @ 0 extent: 66 @ 70).
  11176.     topView addSubView: messageCategoryListView toRightOf: classListView.
  11177.  
  11178.     switchView _ self buildInstanceClassSwitchView.
  11179.     switchView 
  11180.         window: switchView window 
  11181.         viewport: (classListView viewport bottomLeft 
  11182.                     corner: messageCategoryListView viewport bottomLeft).
  11183.     switchView borderWidth: 1.
  11184.     topView addSubView: switchView below: classListView.
  11185.  
  11186.     messageListView _ PluggableListView on: self
  11187.         list: #messageList
  11188.         selected: #messageListIndex
  11189.         changeSelected: #messageListIndex:
  11190.         menu: #messageListMenu:shifted:
  11191.         keystroke: #messageListKey:from:.
  11192.     messageListView window: (0 @ 0 extent: 67 @ 70).
  11193.     topView addSubView: messageListView toRightOf: messageCategoryListView.
  11194.  
  11195.     browserCodeView _ PluggableTextView on: self 
  11196.             text: #contents accept: #contents:notifying:
  11197.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  11198.     browserCodeView window: (0@0 extent: 200@(110-12)).
  11199.     topView addSubView: browserCodeView below: switchView.
  11200.     aString ifNotNil: [browserCodeView editString: aString.
  11201.             browserCodeView hasUnacceptedEdits: true].
  11202.     ^ topView
  11203. ! !
  11204.  
  11205. !Browser methodsFor: 'initialize-release' stamp: 'tk 5/2/1998 14:35'!
  11206. setClass: aBehavior selector: aSymbol
  11207.     "Set the state of a new, uninitialized Browser."
  11208.  
  11209.     | isMeta aClass systemCatIndex messageCatIndex |
  11210.     aBehavior ifNil: [^ self].
  11211.     (aBehavior isKindOf: Metaclass)
  11212.         ifTrue: [isMeta _ true. aClass _ aBehavior soleInstance]
  11213.         ifFalse: [isMeta _ false. aClass _ aBehavior].
  11214.     systemCatIndex _ SystemOrganization categories indexOf: aClass category.
  11215.     self systemCategoryListIndex: systemCatIndex.
  11216.     self classListIndex:
  11217.             ((SystemOrganization listAtCategoryNumber: systemCatIndex)
  11218.                     indexOf: aClass name).
  11219.     self metaClassIndicated: isMeta.
  11220.     aSymbol ifNil: [^ self].
  11221.     messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol.
  11222.     self messageCategoryListIndex: messageCatIndex.
  11223.     messageCatIndex = 0 ifTrue: [^ self].
  11224.     self messageListIndex:
  11225.             ((aBehavior organization listAtCategoryNumber: messageCatIndex)
  11226.                     indexOf: aSymbol).
  11227. ! !
  11228.  
  11229. !Browser methodsFor: 'initialize-release'!
  11230. systemOrganizer: aSystemOrganizer 
  11231.     "Initialize the receiver as a perspective on the system organizer, 
  11232.     aSystemOrganizer. Typically there is only one--the system variable 
  11233.     SystemOrganization."
  11234.  
  11235.     super initialize.
  11236.     contents _ nil.
  11237.     systemOrganizer _ aSystemOrganizer.
  11238.     systemCategoryListIndex _ 0.
  11239.     classListIndex _ 0.
  11240.     messageCategoryListIndex _ 0.
  11241.     messageListIndex _ 0.
  11242.     metaClassIndicated _ false.
  11243.     self setClassOrganizer.
  11244.     editSelection _ #none! !
  11245.  
  11246.  
  11247. !Browser methodsFor: 'accessing' stamp: 'tk 4/9/98 13:47'!
  11248. contents
  11249.     "Depending on the current selection, different information is retrieved.
  11250.     Answer a string description of that information. This information is the
  11251.     method of the currently selected class and message."
  11252.     | comment theClass |
  11253.     editSelection == #none ifTrue: [^ ''].
  11254.     editSelection == #editSystemCategories 
  11255.         ifTrue: [^ systemOrganizer printString].
  11256.     editSelection == #newClass 
  11257.         ifTrue: [^ Class template: self selectedSystemCategoryName].
  11258.     editSelection == #editClass 
  11259.         ifTrue: [^ self selectedClassOrMetaClass definition].
  11260.     editSelection == #editComment 
  11261.         ifTrue: [(theClass _ self selectedClass) ifNil: [^ ''].
  11262.                 comment _ theClass comment.
  11263.                 comment size = 0
  11264.                 ifTrue: [ ^ 'This class has not yet been commented.']
  11265.                 ifFalse: [ ^ comment]].
  11266.     editSelection == #hierarchy 
  11267.         ifTrue: [^ self selectedClassOrMetaClass printHierarchy].
  11268.     editSelection == #editMessageCategories 
  11269.         ifTrue: [^ self classOrMetaClassOrganizer printString].
  11270.     editSelection == #newMessage
  11271.         ifTrue: [^ self selectedClassOrMetaClass sourceCodeTemplate].
  11272.     editSelection == #editMessage
  11273.         ifTrue: [^ self selectedMessage].
  11274.     editSelection == #byteCodes ifTrue: [
  11275.         ^ (self selectedClassOrMetaClass compiledMethodAt: 
  11276.                 self selectedMessageName) symbolic asText].
  11277.  
  11278.     self error: 'Browser internal error: unknown edit selection.'! !
  11279.  
  11280. !Browser methodsFor: 'accessing' stamp: 'di 1/14/98 14:01'!
  11281. contents: input notifying: aController 
  11282.     "The retrieved information has changed and its source must now be 
  11283.     updated. The information can be a variety of things, depending on the 
  11284.     list selections (such as templates for class or message definition, methods) 
  11285.     or the user menu commands (such as definition, comment, hierarchy). 
  11286.     Answer the result of updating the source."
  11287.     | aString aText theClass |
  11288.     aString _ input asString.
  11289.     aText _ input asText.
  11290.  
  11291.     editSelection == #editSystemCategories 
  11292.         ifTrue: [^ self changeSystemCategories: aString].
  11293.     editSelection == #editClass | (editSelection == #newClass) 
  11294.         ifTrue: [^ self defineClass: aString notifying: aController].
  11295.     editSelection == #editComment 
  11296.         ifTrue: [theClass _ self selectedClass.
  11297.                 theClass ifNil: [PopUpMenu notify: 'You must select a class
  11298. before giving it a comment.'.
  11299.                 ^ false].
  11300.                 theClass comment: aText. ^ true].
  11301.     editSelection == #hierarchy ifTrue: [^ true].
  11302.     editSelection == #editMessageCategories 
  11303.         ifTrue: [^ self changeMessageCategories: aString].
  11304.     editSelection == #editMessage | (editSelection == #newMessage) 
  11305.         ifTrue: [^ self defineMessage: aText notifying: aController].
  11306.     editSelection == #none
  11307.         ifTrue: [PopUpMenu notify: 'This text cannot be accepted
  11308. in this part of the browser.'.
  11309.                 ^ false].
  11310.     self error: 'unacceptable accept'! !
  11311.  
  11312. !Browser methodsFor: 'accessing' stamp: 'tk 4/2/98 13:33'!
  11313. contentsSelection
  11314.     "Return the interval of text in the code pane to select when I set the pane's contents"
  11315.  
  11316.     messageCategoryListIndex > 0 & (messageListIndex = 0) 
  11317.         ifTrue: [^ 1 to: 500]    "entire empty method template"
  11318.         ifFalse: [^ 1 to: 0]  "null selection"! !
  11319.  
  11320. !Browser methodsFor: 'accessing' stamp: 'di 5/6/1998 20:57'!
  11321. couldBrowseAnyClass
  11322.     "Answer whether the receiver is equipped to browse any class. This is in support of the system-brower feature that allows the browser to be redirected at the selected class name.  This implementation is clearly ugly, but the feature it enables is handsome enough.  3/1/96 sw"
  11323.  
  11324.     self dependents
  11325.         detect: [:d |
  11326.             (d class == PluggableListView) and: 
  11327.             [d getListSelector == #systemCategoryList]]
  11328.         ifNone: [^ false].
  11329.     ^ true
  11330. ! !
  11331.  
  11332. !Browser methodsFor: 'accessing'!
  11333. doItReceiver
  11334.     "This class's classPool has been jimmied to be the classPool of the class being browsed.  A doIt in the code pane will let the user see the value of the class variables."
  11335.     ^ FakeClassPool new! !
  11336.  
  11337. !Browser methodsFor: 'accessing'!
  11338. editSelection
  11339.     ^editSelection! !
  11340.  
  11341. !Browser methodsFor: 'accessing' stamp: 'jm 4/28/1998 05:55'!
  11342. request: prompt initialAnswer: initialAnswer
  11343.  
  11344.     ^ FillInTheBlank
  11345.         request: prompt
  11346.         initialAnswer: initialAnswer
  11347. ! !
  11348.  
  11349. !Browser methodsFor: 'accessing' stamp: 'di 5/20/1998 22:48'!
  11350. spawn: aString 
  11351.     "Create and schedule a new browser as though the command browse were 
  11352.     issued with respect to one of the browser's lists. The initial textual 
  11353.     contents is aString, which is the (modified) textual contents of the 
  11354.     receiver."
  11355.  
  11356.     messageListIndex ~= 0 
  11357.         ifTrue: [^self buildMessageBrowserEditString: aString].
  11358.     messageCategoryListIndex ~= 0 
  11359.         ifTrue: [^self buildMessageCategoryBrowserEditString: aString].
  11360.     classListIndex ~= 0 ifTrue: [^self buildClassBrowserEditString: aString].
  11361.     systemCategoryListIndex ~= 0 
  11362.         ifTrue: [^self buildSystemCategoryBrowserEditString: aString].
  11363.     ^Browser new openEditString: aString! !
  11364.  
  11365.  
  11366. !Browser methodsFor: 'system category list' stamp: 'tk 5/4/1998 15:46'!
  11367. indexIsOne
  11368.     "When used as a singleton list, index is always one"
  11369.     ^ 1! !
  11370.  
  11371. !Browser methodsFor: 'system category list' stamp: 'tk 5/4/1998 15:46'!
  11372. indexIsOne: value
  11373.     "When used as a singleton list, can't change it"
  11374.  
  11375.     ^ self! !
  11376.  
  11377. !Browser methodsFor: 'system category list'!
  11378. selectedSystemCategoryName
  11379.     "Answer the name of the selected system category or nil."
  11380.  
  11381.     systemCategoryListIndex = 0 ifTrue: [^nil].
  11382.     ^self systemCategoryList at: systemCategoryListIndex! !
  11383.  
  11384. !Browser methodsFor: 'system category list'!
  11385. systemCategoryList
  11386.     "Answer the class categories modelled by the receiver."
  11387.  
  11388.     ^systemOrganizer categories! !
  11389.  
  11390. !Browser methodsFor: 'system category list'!
  11391. systemCategoryListIndex
  11392.     "Answer the index of the selected class category."
  11393.  
  11394.     ^systemCategoryListIndex! !
  11395.  
  11396. !Browser methodsFor: 'system category list' stamp: 'tk 4/2/98 13:41'!
  11397. systemCategoryListIndex: anInteger 
  11398.     "Set the selected system category index to be anInteger. Update all other 
  11399.     selections to be deselected."
  11400.  
  11401.     systemCategoryListIndex _ anInteger.
  11402.     classListIndex _ 0.
  11403.     messageCategoryListIndex _ 0.
  11404.     messageListIndex _ 0.
  11405.     editSelection _ anInteger = 0 ifTrue: [#none] ifFalse: [#newClass].
  11406.     metaClassIndicated _ false.
  11407.     self setClassOrganizer.
  11408.     contents _ nil.
  11409.     self changed: #systemCategorySelectionChanged.
  11410.     self changed: #systemCategoryListIndex.    "update my selection"
  11411.     self changed: #classList.
  11412.     self changed: #messageCategoryList.
  11413.     self changed: #messageList.
  11414.     self changed: #contents.
  11415. ! !
  11416.  
  11417. !Browser methodsFor: 'system category list' stamp: 'tk 4/3/98 10:30'!
  11418. systemCategorySingleton
  11419.  
  11420.     | cat |
  11421.     cat _ self selectedSystemCategoryName.
  11422.     ^ cat ifNil: [Array new]
  11423.         ifNotNil: [Array with: cat]! !
  11424.  
  11425. !Browser methodsFor: 'system category list'!
  11426. toggleSystemCategoryListIndex: anInteger 
  11427.     "If anInteger is the current system category index, deselect it. Else make 
  11428.     it the current system category selection."
  11429.  
  11430.     self systemCategoryListIndex: 
  11431.         (systemCategoryListIndex = anInteger
  11432.             ifTrue: [0]
  11433.             ifFalse: [anInteger])! !
  11434.  
  11435.  
  11436. !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:56'!
  11437. addSystemCategory
  11438.     "Prompt for a new category name and add it before the
  11439.     current selection, or at the end if no current selection"
  11440.     | oldIndex newName |
  11441.     self okToChange ifFalse: [^ self].
  11442.     oldIndex _ systemCategoryListIndex.
  11443.     newName _ self
  11444.         request: 'Please type new category name'
  11445.         initialAnswer: 'Category-Name'.
  11446.     newName isEmpty
  11447.         ifTrue: [^ self]
  11448.         ifFalse: [newName _ newName asSymbol].
  11449.     systemOrganizer
  11450.         addCategory: newName
  11451.         before: (systemCategoryListIndex = 0
  11452.                 ifTrue: [nil]
  11453.                 ifFalse: [self selectedSystemCategoryName]).
  11454.     self systemCategoryListIndex:
  11455.         (oldIndex = 0
  11456.             ifTrue: [systemOrganizer categories size]
  11457.             ifFalse: [oldIndex]).
  11458.     self changed: #systemCategoryList.! !
  11459.  
  11460. !Browser methodsFor: 'system category functions' stamp: 'tk 4/6/98 21:09'!
  11461. browseAllClasses
  11462.     "Create and schedule a new browser on all classes alphabetically."
  11463.     | newBrowser |
  11464.     newBrowser _ HierarchyBrowser new initAlphabeticListing.
  11465.     Browser openBrowserView: (newBrowser openSystemCatEditString: nil)
  11466.         label: 'All Classes Alphabetically'! !
  11467.  
  11468. !Browser methodsFor: 'system category functions'!
  11469. buildSystemCategoryBrowser
  11470.     "Create and schedule a new system category browser."
  11471.  
  11472.     self buildSystemCategoryBrowserEditString: nil! !
  11473.  
  11474. !Browser methodsFor: 'system category functions' stamp: 'tk 5/4/1998 15:56'!
  11475. buildSystemCategoryBrowserEditString: aString 
  11476.     "Create and schedule a new system category browser with initial textual 
  11477.     contents set to aString."
  11478.  
  11479.     | newBrowser |
  11480.     systemCategoryListIndex > 0
  11481.         ifTrue: 
  11482.             [newBrowser _ Browser new.
  11483.             newBrowser systemCategoryListIndex: systemCategoryListIndex.
  11484.             newBrowser setClass: self selectedClassOrMetaClass selector: self selectedMessageName.
  11485.             Browser openBrowserView: (newBrowser openSystemCatEditString: aString)
  11486.                 label: 'Classes in category ', newBrowser selectedSystemCategoryName]! !
  11487.  
  11488. !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:21'!
  11489. changeSystemCategories: aString 
  11490.     "Update the class categories by parsing the argument aString."
  11491.  
  11492.     systemOrganizer changeFromString: aString.
  11493.     self changed: #systemCategoryList.
  11494.     ^ true! !
  11495.  
  11496. !Browser methodsFor: 'system category functions' stamp: 'tk 4/2/98 13:43'!
  11497. classNotFound
  11498.  
  11499.     self changed: #flash.! !
  11500.  
  11501. !Browser methodsFor: 'system category functions' stamp: 'tk 4/2/98 13:44'!
  11502. editSystemCategories
  11503.     "Retrieve the description of the class categories of the system organizer."
  11504.  
  11505.     self okToChange ifFalse: [^ self].
  11506.     self systemCategoryListIndex: 0.
  11507.     editSelection _ #editSystemCategories.
  11508.     self changed: #editSystemCategories.
  11509.     self changed: #contents! !
  11510.  
  11511. !Browser methodsFor: 'system category functions' stamp: 'tk 3/31/98 07:52'!
  11512. fileOutSystemCategory
  11513.     "Print a description of each class in the selected category onto a file 
  11514.     whose name is the category name followed by .st."
  11515.  
  11516.     systemCategoryListIndex ~= 0
  11517.         ifTrue: [systemOrganizer fileOutCategory: self selectedSystemCategoryName]! !
  11518.  
  11519. !Browser methodsFor: 'system category functions' stamp: 'tk 4/2/98 13:44'!
  11520. findClass
  11521.     "Search for a class by name.  Modified so that if only 1 class matches the user-supplied string, or if the user-supplied string exactly matches a class name, then the pop-up menu is bypassed"
  11522.     | pattern foundClass classNames index reply |
  11523.  
  11524.     self okToChange ifFalse: [^ self classNotFound].
  11525.     pattern _ (reply _ FillInTheBlank request: 'Class Name?') asLowercase.
  11526.     pattern isEmpty ifTrue: [^ self classNotFound].
  11527.     (Smalltalk hasClassNamed: reply)
  11528.         ifTrue:
  11529.             [foundClass _ Smalltalk at: reply asSymbol]
  11530.         ifFalse:
  11531.              [classNames _ Smalltalk classNames asArray select: 
  11532.                 [:n | (n asLowercase indexOfSubCollection: pattern startingAt: 1) > 0].
  11533.             classNames isEmpty ifTrue: [^ self classNotFound].
  11534.             index _ classNames size == 1
  11535.                 ifTrue:    [1]
  11536.                 ifFalse:    [(PopUpMenu labelArray: classNames lines: #()) startUp].
  11537.             index = 0 ifTrue: [^ self classNotFound].
  11538.             foundClass _ Smalltalk at: (classNames at: index)].
  11539.      self systemCategoryListIndex: (self systemCategoryList indexOf: foundClass category).
  11540.     self classListIndex: (self classList indexOf: foundClass name). 
  11541. ! !
  11542.  
  11543. !Browser methodsFor: 'system category functions' stamp: 'tk 4/2/98 13:46'!
  11544. printOutSystemCategory
  11545.     "Print a description of each class in the selected category as Html."
  11546.  
  11547. Cursor write showWhile:
  11548.     [systemCategoryListIndex ~= 0
  11549.         ifTrue: [systemOrganizer fileOutCategory: self selectedSystemCategoryName
  11550.                                 asHtml: true ]]
  11551. ! !
  11552.  
  11553. !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:55'!
  11554. removeSystemCategory
  11555.     "If a class category is selected, create a Confirmer so the user can 
  11556.     verify that the currently selected class category and all of its classes
  11557.      should be removed from the system. If so, remove it."
  11558.  
  11559.     systemCategoryListIndex = 0 ifTrue: [^ self].
  11560.     self okToChange ifFalse: [^ self].
  11561.     (self classList size = 0
  11562.         or: [self confirm: 'Are you sure you want to
  11563. remove this system category 
  11564. and all its classes?'])
  11565.         ifTrue: 
  11566.         [systemOrganizer removeSystemCategory: self selectedSystemCategoryName.
  11567.         self systemCategoryListIndex: 0.
  11568.         self changed: #systemCategoryList]! !
  11569.  
  11570. !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:55'!
  11571. renameSystemCategory
  11572.     "Prompt for a new category name and add it before the
  11573.     current selection, or at the end if no current selection"
  11574.     | oldIndex oldName newName |
  11575.     (oldIndex _ systemCategoryListIndex) = 0
  11576.         ifTrue: [^ self].  "no selection"
  11577.     self okToChange ifFalse: [^ self].
  11578.     oldName _ self selectedSystemCategoryName.
  11579.     newName _ self
  11580.         request: 'Please type new category name'
  11581.         initialAnswer: oldName.
  11582.     newName isEmpty
  11583.         ifTrue: [^ self]
  11584.         ifFalse: [newName _ newName asSymbol].
  11585.     oldName = newName ifTrue: [^ self].
  11586.     systemOrganizer
  11587.         renameCategory: oldName
  11588.         toBe: newName.
  11589.     self systemCategoryListIndex: oldIndex.
  11590.     self changed: #systemCategoryList.! !
  11591.  
  11592. !Browser methodsFor: 'system category functions' stamp: 'tk 4/2/98 13:48'!
  11593. systemCategoryMenu: aMenu
  11594.  
  11595. ^ aMenu labels:
  11596. 'find class...
  11597. recent classes...
  11598. browse all
  11599. browse
  11600. printOut
  11601. fileOut
  11602. reorganize
  11603. update
  11604. add item...
  11605. rename...
  11606. remove' 
  11607.     lines: #(2 4 6 8)
  11608.     selections:
  11609.         #(findClass recent browseAllClasses buildSystemCategoryBrowser
  11610.         printOutSystemCategory fileOutSystemCategory
  11611.         editSystemCategories updateSystemCategories
  11612.         addSystemCategory renameSystemCategory removeSystemCategory )
  11613. ! !
  11614.  
  11615. !Browser methodsFor: 'system category functions' stamp: 'di 4/12/98 13:17'!
  11616. updateSystemCategories
  11617.     "The class categories were changed in another browser. The receiver must 
  11618.     reorganize its lists based on these changes."
  11619.  
  11620.     self okToChange ifFalse: [^ self].
  11621.     self changed: #systemCategoryList! !
  11622.  
  11623.  
  11624. !Browser methodsFor: 'class list'!
  11625. classList
  11626.     "Answer an array of the class names of the selected category. Answer an 
  11627.     empty array if no selection exists."
  11628.  
  11629.     systemCategoryListIndex = 0
  11630.         ifTrue: [^Array new]
  11631.         ifFalse: [^systemOrganizer listAtCategoryNumber: systemCategoryListIndex]! !
  11632.  
  11633. !Browser methodsFor: 'class list'!
  11634. classListIndex
  11635.     "Answer the index of the current class selection."
  11636.  
  11637.     ^classListIndex! !
  11638.  
  11639. !Browser methodsFor: 'class list' stamp: 'tk 4/2/98 13:30'!
  11640. classListIndex: anInteger 
  11641.     "Set anInteger to be the index of the current class selection."
  11642.  
  11643.     | className |
  11644.     classListIndex _ anInteger.
  11645.     self setClassOrganizer.
  11646.     messageCategoryListIndex _ 0.
  11647.     messageListIndex _ 0.
  11648.     self classCommentIndicated
  11649.         ifTrue: []
  11650.         ifFalse: [editSelection _ anInteger = 0
  11651.                     ifTrue: [metaClassIndicated
  11652.                         ifTrue: [#none]
  11653.                         ifFalse: [#newClass]]
  11654.                     ifFalse: [#editClass]].
  11655.     contents _ nil.
  11656.     self selectedClass isNil
  11657.         ifFalse: [className _ self selectedClass name.
  11658.                     (RecentClasses includes: className)
  11659.                 ifTrue: [RecentClasses remove: className].
  11660.             RecentClasses addFirst: className.
  11661.             RecentClasses size > 16
  11662.                 ifTrue: [RecentClasses removeLast]].
  11663.     self changed: #classSelectionChanged.
  11664.     self changed: #classListIndex.    "update my selection"
  11665.     self changed: #messageCategoryList.
  11666.     self changed: #messageList.
  11667.     self changed: #contents.
  11668. ! !
  11669.  
  11670. !Browser methodsFor: 'class list' stamp: 'tk 4/5/98 12:25'!
  11671. classListSingleton
  11672.  
  11673.     | name |
  11674.     name _ self selectedClassName.
  11675.     ^ name ifNil: [Array new]
  11676.         ifNotNil: [Array with: name]! !
  11677.  
  11678. !Browser methodsFor: 'class list' stamp: 'sw 12/19/96'!
  11679. recent
  11680.     "Let the user select from a list of recently visited classes.  11/96 stp.
  11681.      12/96 di:  use class name, not classes themselves.
  11682.      : dont fall into debugger in empty case"
  11683.  
  11684.     | className class recentList |
  11685.     recentList _ RecentClasses select: [:n | Smalltalk includesKey: n].
  11686.     recentList size == 0 ifTrue: [^ self beep].
  11687.     className := (SelectionMenu selections: recentList) startUp.
  11688.     className == nil ifTrue: [^ self].
  11689.     class := Smalltalk at: className.
  11690.     self systemCategoryListIndex: (self systemCategoryList indexOf: class category).
  11691.     self classListIndex: (self classList indexOf: class name)! !
  11692.  
  11693. !Browser methodsFor: 'class list'!
  11694. selectClass: classNotMeta
  11695.     self classListIndex: (self classList findFirst: [:each | each == classNotMeta name])! !
  11696.  
  11697. !Browser methodsFor: 'class list' stamp: 'tk 4/4/98 18:48'!
  11698. selectedClass
  11699.     "Answer the class that is currently selected. Answer nil if no selection 
  11700.     exists."
  11701.  
  11702.     | name |
  11703.     (name _ self selectedClassName) ifNil: [^ nil].
  11704.     ^ Smalltalk at: name! !
  11705.  
  11706. !Browser methodsFor: 'class list'!
  11707. selectedClassName
  11708.     "Answer the name of the current class. Answer nil if no selection exists."
  11709.  
  11710.     classListIndex = 0 ifTrue: [^nil].
  11711.     ^self classList at: classListIndex! !
  11712.  
  11713. !Browser methodsFor: 'class list'!
  11714. toggleClassListIndex: anInteger 
  11715.     "If anInteger is the current class index, deselect it. Else make it the 
  11716.     current class selection."
  11717.  
  11718.     self classListIndex: 
  11719.         (classListIndex = anInteger
  11720.             ifTrue: [0]
  11721.             ifFalse: [anInteger])! !
  11722.  
  11723.  
  11724. !Browser methodsFor: 'class functions'!
  11725. buildClassBrowser
  11726.     "Create and schedule a new class category browser for the current class 
  11727.     selection, if one exists."
  11728.  
  11729.     self buildClassBrowserEditString: nil! !
  11730.  
  11731. !Browser methodsFor: 'class functions' stamp: 'tk 4/7/98 13:15'!
  11732. buildClassBrowserEditString: aString 
  11733.     "Create and schedule a new class browser for the current selection, if one 
  11734.     exists, with initial textual contents set to aString."
  11735.  
  11736.     | newBrowser |
  11737.     self selectedClass ifNotNil:
  11738.         [newBrowser _ Browser new.
  11739.         newBrowser setClass: self selectedClassOrMetaClass selector: self selectedMessageName.
  11740.         Browser openBrowserView: (newBrowser openOnClassWithEditString: aString)
  11741.             label: 'Class Browser: ', self selectedClassOrMetaClass name]
  11742. ! !
  11743.  
  11744. !Browser methodsFor: 'class functions' stamp: 'tk 4/10/1998 12:44'!
  11745. classListMenu: aMenu
  11746.  
  11747. ^ aMenu labels: 
  11748. 'browse class
  11749. browse full
  11750. printOut
  11751. fileOut
  11752. hierarchy
  11753. definition
  11754. comment
  11755. spawn hierarchy
  11756. spawn protocol
  11757. inst var refs..
  11758. inst var defs..
  11759. class var refs...
  11760. class vars
  11761. class refs
  11762. rename...
  11763. remove
  11764. unsent methods
  11765. find method...' 
  11766.     lines: #(4 7 9 11 14 16)
  11767.     selections:
  11768.         #(buildClassBrowser browseMethodFull printOutClass fileOutClass
  11769.         hierarchy editClass editComment
  11770.         spawnHierarchy spawnProtocol
  11771.         browseInstVarRefs browseInstVarDefs browseClassVarRefs 
  11772.         browseClassVariables browseClassRefs
  11773.         renameClass removeClass browseUnusedMethods findMethod)
  11774. ! !
  11775.  
  11776. !Browser methodsFor: 'class functions' stamp: 'tk 4/24/1998 23:52'!
  11777. defineClass: aString notifying: aController 
  11778.     "The receiver's textual content is a request to define a new class. The 
  11779.     source code is aString. If any errors occur in compilation, notify 
  11780.     aController."
  11781.  
  11782.     | oldClass class |
  11783.     oldClass _ self selectedClassOrMetaClass.
  11784.     oldClass isNil ifTrue: [oldClass _ Object].
  11785.     class _ oldClass subclassDefinerClass
  11786.                 evaluate: aString
  11787.                 notifying: aController
  11788.                 logged: true.
  11789.     (class isKindOf: Behavior)
  11790.         ifTrue: 
  11791.             [self changed: #classList.
  11792.             self classListIndex: 
  11793.                 (self classList indexOf: 
  11794.                     ((class isKindOf: Metaclass)
  11795.                         ifTrue: [class soleInstance name]
  11796.                         ifFalse: [class name])).
  11797.             self clearUserEditFlag; editClass.
  11798.             ^true]
  11799.         ifFalse: [^false]! !
  11800.  
  11801. !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:49'!
  11802. editClass
  11803.     "Retrieve the description of the class definition."
  11804.  
  11805.     classListIndex = 0 ifTrue: [^ self].
  11806.     self okToChange ifFalse: [^ self].
  11807.     self messageCategoryListIndex: 0.
  11808.     editSelection _ #editClass.
  11809.     self changed: #editClass.
  11810.     self changed: #contents.
  11811. ! !
  11812.  
  11813. !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:49'!
  11814. editComment
  11815.     "Retrieve the description of the class comment."
  11816.  
  11817.     classListIndex = 0 ifTrue: [^ self].
  11818.     self okToChange ifFalse: [^ self].
  11819.     self messageCategoryListIndex: 0.
  11820.     editSelection _ #editComment.
  11821.     self changed: #classSelectionChanged.
  11822.     self changed: #contents.
  11823. ! !
  11824.  
  11825. !Browser methodsFor: 'class functions'!
  11826. explainSpecial: string 
  11827.     "Answer a string explaining the code pane selection if it is displaying 
  11828.     one of the special edit functions."
  11829.  
  11830.     | classes whole lits reply |
  11831.     (editSelection == #editClass or: [editSelection == #newClass])
  11832.         ifTrue: 
  11833.             ["Selector parts in class definition"
  11834.             string last == $: ifFalse: [^nil].
  11835.             lits _ Array with:
  11836.                 #subclass:instanceVariableNames:classVariableNames:poolDictionaries:category:.
  11837.             (whole _ lits detect: [:each | (each keywords
  11838.                     detect: [:frag | frag = string] ifNone: []) ~~ nil]
  11839.                         ifNone: []) ~~ nil
  11840.                 ifTrue: [reply _ '"' , string , ' is one part of the message selector ' , whole , '.']
  11841.                 ifFalse: [^nil].
  11842.             classes _ Smalltalk allClassesImplementing: whole.
  11843.             classes _ 'these classes ' , classes printString.
  11844.             ^reply , '  It is defined in ' , classes , '."
  11845. Smalltalk browseAllImplementorsOf: #' , whole].
  11846.  
  11847.     editSelection == #hierarchy
  11848.         ifTrue: 
  11849.             ["Instance variables in subclasses"
  11850.             classes _ self selectedClassOrMetaClass allSubclasses.
  11851.             classes _ classes detect: [:each | (each instVarNames
  11852.                         detect: [:name | name = string] ifNone: []) ~~ nil]
  11853.                     ifNone: [^nil].
  11854.             classes _ classes printString.
  11855.             ^'"is an instance variable in class ' , classes , '."
  11856. ' , classes , ' browseAllAccessesTo: ''' , string , '''.'].
  11857.     editSelection == #editSystemCategories ifTrue: [^nil].
  11858.     editSelection == #editMessageCategories ifTrue: [^nil].
  11859.     ^nil! !
  11860.  
  11861. !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:50'!
  11862. fileOutClass
  11863.     "Print a description of the selected class onto a file whose name is the 
  11864.     category name followed by .st."
  11865.  
  11866. Cursor write showWhile:
  11867.         [classListIndex ~= 0 ifTrue: [self selectedClass fileOut]]! !
  11868.  
  11869. !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:50'!
  11870. findMethod
  11871.     "Pop up a list of the current class's methods, and select the one chosen by the user.
  11872.     5/21/96 sw, based on a suggestion of John Maloney's."
  11873.     | aClass selectors reply cat messageCatIndex messageIndex |
  11874.  
  11875.     self classListIndex = 0 ifTrue: [^ self].
  11876.     self okToChange ifFalse: [^ self].
  11877.     aClass _ self selectedClassOrMetaClass.
  11878.     selectors _ aClass selectors asSortedArray.
  11879.     reply _ (SelectionMenu labelList: selectors selections: selectors) startUp.
  11880.     reply == nil ifTrue: [^ self].
  11881.     cat _ aClass whichCategoryIncludesSelector: reply.
  11882.     messageCatIndex _ self messageCategoryList indexOf: cat.
  11883.     self messageCategoryListIndex: messageCatIndex.
  11884.     messageIndex _ (self messageList indexOf: reply).
  11885.     self messageListIndex: messageIndex.
  11886. ! !
  11887.  
  11888. !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:50'!
  11889. hierarchy
  11890.     "Display the inheritance hierarchy of the receiver's selected class."
  11891.  
  11892.     classListIndex = 0 ifTrue: [^ self].
  11893.     self okToChange ifFalse: [^ self].
  11894.     self messageCategoryListIndex: 0.
  11895.     editSelection := #hierarchy.
  11896.     self changed: #editComment.
  11897.     self changed: #contents.
  11898.     ^ self! !
  11899.  
  11900. !Browser methodsFor: 'class functions' stamp: 'tk 4/2/98 13:50'!
  11901. printOutClass
  11902.     "Print a description of the selected class onto a file whose name is the 
  11903.     category name followed by .html."
  11904.  
  11905. Cursor write showWhile:
  11906.         [classListIndex ~= 0 ifTrue: [self selectedClass fileOutAsHtml: true]]! !
  11907.  
  11908. !Browser methodsFor: 'class functions' stamp: 'tk 4/24/1998 23:52'!
  11909. removeClass
  11910.     "The selected class should be removed from the system. Use a Confirmer 
  11911.     to make certain the user intends this irrevocable command to be carried 
  11912.     out."
  11913.     | message class className |
  11914.     classListIndex = 0 ifTrue: [^ self].
  11915.     self okToChange ifFalse: [^ self].
  11916.     class _ self selectedClass.
  11917.     className _ class name.
  11918.     message _ 'Are you certain that you
  11919. want to delete the class ', className, '?'.
  11920.     (self confirm: message) ifTrue: 
  11921.             [class subclasses size > 0
  11922.                 ifTrue: [self notify: 'class has subclasses: ' , message].
  11923.             class removeFromSystem.
  11924.             self classListIndex: 0].
  11925.     self changed: #classList.
  11926. ! !
  11927.  
  11928. !Browser methodsFor: 'class functions' stamp: 'tk 4/24/1998 23:54'!
  11929. renameClass
  11930.     | oldName newName obs |
  11931.     classListIndex = 0 ifTrue: [^ self].
  11932.     self okToChange ifFalse: [^ self].
  11933.     oldName _ self selectedClass name.
  11934.     newName _ (self request: 'Please type new class name'
  11935.                         initialAnswer: oldName) asSymbol.
  11936.     newName = oldName ifTrue: [^ self].
  11937.     (Smalltalk includesKey: newName)
  11938.         ifTrue: [^ self error: newName , ' already exists'].
  11939.     self selectedClass rename: newName.
  11940.     self changed: #classList.
  11941.     self classListIndex: ((systemOrganizer listAtCategoryNamed: self selectedSystemCategoryName) indexOf: newName).
  11942.     obs _ Smalltalk allCallsOn: (Smalltalk associationAt: newName).
  11943.     obs isEmpty ifFalse:
  11944.         [Smalltalk browseMessageList: obs
  11945.             name: 'Obsolete References to ' , oldName
  11946.             autoSelect: oldName].
  11947. ! !
  11948.  
  11949. !Browser methodsFor: 'class functions' stamp: 'tk 4/7/98 13:25'!
  11950. spawnHierarchy
  11951.     "Create and schedule a new class hierarchy browser on the currently selected class or meta."
  11952.     | newBrowser aSymbol aBehavior messageCatIndex |
  11953.     classListIndex = 0 ifTrue: [^ self].
  11954.     newBrowser _ HierarchyBrowser new initHierarchyForClass: self selectedClass 
  11955.             meta: self metaClassIndicated.
  11956.     (aSymbol _ self selectedMessageName) ifNotNil: [
  11957.         aBehavior _ self selectedClassOrMetaClass.
  11958.         messageCatIndex _ aBehavior organization numberOfCategoryOfElement: aSymbol.
  11959.         newBrowser messageCategoryListIndex: messageCatIndex.
  11960.         newBrowser messageListIndex:
  11961.             ((aBehavior organization listAtCategoryNumber: messageCatIndex)
  11962.                         indexOf: aSymbol)].
  11963.     Browser openBrowserView: (newBrowser openSystemCatEditString: nil)
  11964.         label: self selectedClassName , ' hierarchy'! !
  11965.  
  11966. !Browser methodsFor: 'class functions' stamp: 'di 7/13/97 16:43'!
  11967. spawnProtocol
  11968.         "Create and schedule a new protocol browser on the currently selected class or meta."
  11969.         classListIndex = 0 ifTrue: [^ self].
  11970.         ProtocolBrowser openSubProtocolForClass: self selectedClassOrMetaClass  ! !
  11971.  
  11972.  
  11973. !Browser methodsFor: 'message category list' stamp: 'tk 4/5/98 12:25'!
  11974. messageCatListSingleton
  11975.  
  11976.     | name |
  11977.     name _ self selectedMessageCategoryName.
  11978.     ^ name ifNil: [Array new]
  11979.         ifNotNil: [Array with: name]! !
  11980.  
  11981. !Browser methodsFor: 'message category list'!
  11982. messageCategoryList
  11983.     "Answer the selected category of messages."
  11984.  
  11985.     classListIndex = 0
  11986.         ifTrue: [^Array new]
  11987.         ifFalse: [^self classOrMetaClassOrganizer categories]! !
  11988.  
  11989. !Browser methodsFor: 'message category list'!
  11990. messageCategoryListIndex
  11991.     "Answer the index of the selected message category."
  11992.  
  11993.     ^messageCategoryListIndex! !
  11994.  
  11995. !Browser methodsFor: 'message category list' stamp: 'tk 4/2/98 13:41'!
  11996. messageCategoryListIndex: anInteger 
  11997.     "Set the selected message category to be the one indexed by anInteger."
  11998.  
  11999.     messageCategoryListIndex _ anInteger.
  12000.     messageListIndex _ 0.
  12001.     editSelection _ 
  12002.         anInteger = 0
  12003.             ifTrue: [#none]
  12004.             ifFalse: [#newMessage].
  12005.     contents _ nil.
  12006.     self changed: #messageCategorySelectionChanged.
  12007.     self changed: #messageCategoryListIndex.    "update my selection"
  12008.     self changed: #messageList.
  12009.     self changed: #contents.
  12010. ! !
  12011.  
  12012. !Browser methodsFor: 'message category list'!
  12013. selectedMessageCategoryName
  12014.     "Answer the name of the selected message category, if any. Answer nil 
  12015.     otherwise."
  12016.  
  12017.     messageCategoryListIndex = 0 ifTrue: [^nil].
  12018.     ^self messageCategoryList at: messageCategoryListIndex! !
  12019.  
  12020. !Browser methodsFor: 'message category list'!
  12021. toggleMessageCategoryListIndex: anInteger 
  12022.     "If the currently selected message category index is anInteger, deselect 
  12023.     the category. Otherwise select the category whose index is anInteger."
  12024.  
  12025.     self messageCategoryListIndex: 
  12026.         (messageCategoryListIndex = anInteger
  12027.             ifTrue: [0]
  12028.             ifFalse: [anInteger])! !
  12029.  
  12030.  
  12031. !Browser methodsFor: 'message category functions' stamp: 'di 5/19/1998 23:58'!
  12032. addCategory
  12033.     "Prompt for a new category name and add it before the
  12034.     current selection, or at the end if no current selection"
  12035.     | oldIndex newName |
  12036.     self okToChange ifFalse: [^ self].
  12037.     classListIndex = 0 ifTrue: [^ self].
  12038.     oldIndex _ messageCategoryListIndex.
  12039.     newName _ self
  12040.         request: 'Please type new category name'
  12041.         initialAnswer: 'category name'.
  12042.     newName isEmpty
  12043.         ifTrue: [^ self]
  12044.         ifFalse: [newName _ newName asSymbol].
  12045.     self classOrMetaClassOrganizer
  12046.         addCategory: newName
  12047.         before: (messageCategoryListIndex = 0
  12048.                 ifTrue: [nil]
  12049.                 ifFalse: [self selectedMessageCategoryName]).
  12050.     self changed: #messageCategoryList.
  12051.     self messageCategoryListIndex:
  12052.         (oldIndex = 0
  12053.             ifTrue: [self classOrMetaClassOrganizer categories size]
  12054.             ifFalse: [oldIndex]).
  12055.     self changed: #messageCategoryList.
  12056. ! !
  12057.  
  12058. !Browser methodsFor: 'message category functions'!
  12059. buildMessageCategoryBrowser
  12060.     "Create and schedule a message category browser for the currently 
  12061.     selected message category."
  12062.  
  12063.     self buildMessageCategoryBrowserEditString: nil! !
  12064.  
  12065. !Browser methodsFor: 'message category functions' stamp: 'tk 5/6/1998 21:30'!
  12066. buildMessageCategoryBrowserEditString: aString 
  12067.     "Create and schedule a message category browser for the currently 
  12068.     selected     message category. The initial text view contains the characters 
  12069.     in aString."
  12070.  
  12071.     | newBrowser |
  12072.     messageCategoryListIndex ~= 0
  12073.         ifTrue: 
  12074.             [newBrowser _ Browser new.
  12075.             newBrowser systemCategoryListIndex: systemCategoryListIndex.
  12076.             newBrowser classListIndex: classListIndex.
  12077.             newBrowser metaClassIndicated: metaClassIndicated.
  12078.             newBrowser messageCategoryListIndex: messageCategoryListIndex.
  12079.             newBrowser messageListIndex: messageListIndex.
  12080.             Browser openBrowserView: (newBrowser openMessageCatEditString: aString)
  12081.                 label: 'Message Category Browser (' , 
  12082.                         newBrowser selectedClassOrMetaClassName , ')']! !
  12083.  
  12084. !Browser methodsFor: 'message category functions' stamp: 'jm 3/24/98 16:05'!
  12085. changeMessageCategories: aString 
  12086.     "The characters in aString represent an edited version of the the message 
  12087.     categories for the selected class. Update this information in the system 
  12088.     and inform any dependents that the categories have been changed. This 
  12089.     message is invoked because the user had issued the categories command 
  12090.     and edited the message categories. Then the user issued the accept 
  12091.     command."
  12092.  
  12093.     self classOrMetaClassOrganizer changeFromString: aString.
  12094.     Smalltalk changes reorganizeClass: self selectedClassOrMetaClass.
  12095.     self clearUserEditFlag.
  12096.     self editClass.
  12097.     self classListIndex: classListIndex.
  12098.     ^ true! !
  12099.  
  12100. !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:53'!
  12101. editMessageCategories
  12102.     "Indicate to the receiver and its dependents that the message categories of 
  12103.     the selected class have been changed."
  12104.  
  12105.     self okToChange ifFalse: [^ self].
  12106.     classListIndex ~= 0
  12107.         ifTrue: 
  12108.             [self messageCategoryListIndex: 0.
  12109.             editSelection _ #editMessageCategories.
  12110.             self changed: #editMessageCategories.
  12111.             self changed: #contents]! !
  12112.  
  12113. !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:53'!
  12114. fileOutMessageCategories
  12115.     "Print a description of the selected message category of the selected class 
  12116.     onto an external file."
  12117.  
  12118. Cursor write showWhile:
  12119.     [messageCategoryListIndex ~= 0
  12120.         ifTrue: 
  12121.             [self selectedClassOrMetaClass fileOutCategory: self selectedMessageCategoryName]]! !
  12122.  
  12123. !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:53'!
  12124. messageCategoryMenu: aMenu
  12125.  
  12126. ^ aMenu labels:
  12127. 'browse
  12128. printOut
  12129. fileOut
  12130. reorganize
  12131. add item...
  12132. rename...
  12133. remove'
  12134.     lines: #(3 4)
  12135.     selections:
  12136.         #(buildMessageCategoryBrowser printOutMessageCategories fileOutMessageCategories
  12137.         editMessageCategories
  12138.         addCategory renameCategory removeMessageCategory)
  12139. ! !
  12140.  
  12141. !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:53'!
  12142. printOutMessageCategories
  12143.     "Print a description of the selected message category of the selected class 
  12144.     onto an external file in Html format."
  12145.  
  12146. Cursor write showWhile:
  12147.     [messageCategoryListIndex ~= 0
  12148.         ifTrue: 
  12149.             [self selectedClassOrMetaClass fileOutCategory: self selectedMessageCategoryName
  12150.                                         asHtml: true]]! !
  12151.  
  12152. !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:54'!
  12153. removeMessageCategory
  12154.     "If a message category is selected, create a Confirmer so the user can 
  12155.     verify that the currently selected message category should be removed
  12156.      from the system. If so, remove it."
  12157.  
  12158.     | messageCategoryName |
  12159.     messageCategoryListIndex = 0 ifTrue: [^ self].
  12160.     self okToChange ifFalse: [^ self].
  12161.     messageCategoryName _ self selectedMessageCategoryName.
  12162.     (self messageList size = 0
  12163.         or: [self confirm: 'Are you sure you want to
  12164. remove this method category 
  12165. and all its methods?'])
  12166.         ifTrue: 
  12167.             [self selectedClassOrMetaClass removeCategory: messageCategoryName.
  12168.             self messageCategoryListIndex: 0.
  12169.             self changed: #classSelectionChanged].
  12170.     self changed: #messageCategoryList.
  12171. ! !
  12172.  
  12173. !Browser methodsFor: 'message category functions' stamp: 'tk 4/2/98 13:54'!
  12174. renameCategory
  12175.     "Prompt for a new category name and add it before the
  12176.     current selection, or at the end if no current selection"
  12177.     | oldIndex oldName newName |
  12178.     classListIndex = 0 ifTrue: [^ self].
  12179.     self okToChange ifFalse: [^ self].
  12180.     (oldIndex _ messageCategoryListIndex) = 0 ifTrue: [^ self].
  12181.     oldName _ self selectedMessageCategoryName.
  12182.     newName _ self
  12183.         request: 'Please type new category name'
  12184.         initialAnswer: oldName.
  12185.     newName isEmpty
  12186.         ifTrue: [^ self]
  12187.         ifFalse: [newName _ newName asSymbol].
  12188.     newName = oldName ifTrue: [^ self].
  12189.     self classOrMetaClassOrganizer
  12190.         renameCategory: oldName
  12191.         toBe: newName.
  12192.     Smalltalk changes reorganizeClass: self selectedClassOrMetaClass.
  12193.     self classListIndex: classListIndex.
  12194.     self messageCategoryListIndex: oldIndex.
  12195.     self changed: #messageCategoryList.
  12196. ! !
  12197.  
  12198.  
  12199. !Browser methodsFor: 'message list'!
  12200. messageList
  12201.     "Answer an Array of the message selectors of the currently selected 
  12202.     message category. Otherwise, answer a new empty Array."
  12203.  
  12204.     messageCategoryListIndex = 0
  12205.         ifTrue: [^Array new]
  12206.         ifFalse: [^self classOrMetaClassOrganizer 
  12207.                     listAtCategoryNumber: messageCategoryListIndex]! !
  12208.  
  12209. !Browser methodsFor: 'message list'!
  12210. messageListIndex
  12211.     "Answer the index of the selected message selector into the currently 
  12212.     selected message category."
  12213.  
  12214.     ^messageListIndex! !
  12215.  
  12216. !Browser methodsFor: 'message list' stamp: 'tk 4/25/1998 00:11'!
  12217. messageListIndex: anInteger 
  12218.     "Set the selected message selector to be the one indexed by anInteger."
  12219.  
  12220.     messageListIndex _ anInteger.
  12221.     editSelection _ 
  12222.         anInteger = 0
  12223.             ifTrue: [#newMessage]
  12224.             ifFalse: [#editMessage].
  12225.     contents _ nil.
  12226.     self changed: #messageListIndex.    "update my selection"
  12227.     self changed: #contents.
  12228. ! !
  12229.  
  12230. !Browser methodsFor: 'message list' stamp: 'tk 4/6/98 10:48'!
  12231. messageListSingleton
  12232.  
  12233.     | name |
  12234.     name _ self selectedMessageName.
  12235.     ^ name ifNil: [Array new]
  12236.         ifNotNil: [Array with: name]! !
  12237.  
  12238. !Browser methodsFor: 'message list' stamp: 'tk 4/4/98 21:25'!
  12239. selectedMessage
  12240.     "Answer a copy of the source code for the selected message selector."
  12241.     | class selector method tempNames |
  12242.     contents == nil ifFalse: [^ contents copy].
  12243.     class _ self selectedClassOrMetaClass.
  12244.     selector _ self selectedMessageName.
  12245.     method _ class compiledMethodAt: selector.
  12246.  
  12247.     (Sensor controlKeyPressed
  12248.         or: [method fileIndex > 0 and: [(SourceFiles at: method fileIndex) == nil]])
  12249.         ifTrue:
  12250.         ["Emergency or no source file -- decompile without temp names"
  12251.         contents _ (class decompilerClass new decompile: selector in: class method: method)
  12252.             decompileString.
  12253.         ^ contents copy].
  12254.  
  12255.     Sensor leftShiftDown ifTrue:
  12256.         ["Special request to decompile -- get temps from source file"
  12257.         tempNames _ (class compilerClass new
  12258.                         parse: method getSourceFromFile asString in: class notifying: nil)
  12259.                         tempNames.
  12260.         contents _ ((class decompilerClass new withTempNames: tempNames)
  12261.                 decompile: selector
  12262.                 in: class
  12263.                 method: method) decompileString.
  12264.         contents _ contents asText makeSelectorBoldIn: self selectedClassOrMetaClass.
  12265.         ^ contents copy].
  12266.  
  12267.     contents _ class sourceCodeAt: selector.
  12268.     contents _ contents asText makeSelectorBoldIn: self selectedClassOrMetaClass.
  12269.     ^ contents copy! !
  12270.  
  12271. !Browser methodsFor: 'message list'!
  12272. selectedMessageName
  12273.     "Answer the message selector of the currently selected message, if any. 
  12274.     Answer nil otherwise."
  12275.  
  12276.     messageListIndex = 0 ifTrue: [^nil].
  12277.     ^self messageList at: messageListIndex! !
  12278.  
  12279. !Browser methodsFor: 'message list'!
  12280. toggleMessageListIndex: anInteger 
  12281.     "If the currently selected message index is anInteger, deselect the message 
  12282.     selector. Otherwise select the message selector whose index is anInteger."
  12283.  
  12284.     self messageListIndex: 
  12285.         (messageListIndex = anInteger
  12286.             ifTrue: [0]
  12287.             ifFalse: [anInteger])! !
  12288.  
  12289.  
  12290. !Browser methodsFor: 'message functions'!
  12291. browseImplementors
  12292.     "Create and schedule a message set browser on all implementors of the 
  12293.     currently selected message selector. Do nothing if no message is selected."
  12294.  
  12295.     messageListIndex ~= 0 
  12296.         ifTrue: [Smalltalk browseAllImplementorsOf: self selectedMessageName]! !
  12297.  
  12298. !Browser methodsFor: 'message functions'!
  12299. buildMessageBrowser
  12300.     "Create and schedule a message browser on the currently selected 
  12301.     message. Do nothing if no message is selected. The initial text view 
  12302.     contains nothing."
  12303.  
  12304.     self buildMessageBrowserEditString: nil! !
  12305.  
  12306. !Browser methodsFor: 'message functions' stamp: 'tk 4/6/98 21:47'!
  12307. buildMessageBrowserEditString: aString 
  12308.     "Create and schedule a message browser for the receiver in which the 
  12309.     argument, aString, contains characters to be edited in the text view."
  12310.  
  12311.     messageListIndex = 0 ifTrue: [^ self].
  12312.     ^ Browser openMessageBrowserForClass: self selectedClassOrMetaClass 
  12313.         selector: self selectedMessageName editString: aString! !
  12314.  
  12315. !Browser methodsFor: 'message functions' stamp: 'tk 4/25/1998 00:08'!
  12316. defineMessage: aString notifying: aController 
  12317.     "Compile the expressions in aString. Notify aController if a syntax error 
  12318.     occurs. Install the compiled method in the selected class classified under 
  12319.     the currently selected message category name. Answer true if 
  12320.     compilation succeeds, false otherwise."
  12321.     | selectedMessageName selector category oldMessageList |
  12322.     selectedMessageName _ self selectedMessageName.
  12323.     oldMessageList _ self messageList.
  12324.     contents _ nil.
  12325.     selector _ self selectedClassOrMetaClass
  12326.                 compile: aString
  12327.                 classified: (category _ self selectedMessageCategoryName)
  12328.                 notifying: aController.
  12329.     selector == nil ifTrue: [^ false].
  12330.     contents _ aString copy.
  12331.     selector ~~ selectedMessageName
  12332.         ifTrue: 
  12333.             [category = ClassOrganizer nullCategory
  12334.                 ifTrue: [self changed: #classSelectionChanged.
  12335.                         self changed: #classList.
  12336.                         self messageCategoryListIndex: 1].
  12337.             self setClassOrganizer.  "In case organization not cached"
  12338.             (oldMessageList includes: selector)
  12339.                 ifFalse: [self changed: #messageList].
  12340.             self messageListIndex: (self messageList indexOf: selector)].
  12341.     ^ true! !
  12342.  
  12343. !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:02'!
  12344. inspectInstances
  12345.     "Inspect all instances of the selected class.  1/26/96 sw"
  12346.  
  12347.     | myClass |
  12348.     myClass _ self selectedClassOrMetaClass.
  12349.     myClass ~~ nil ifTrue:
  12350.         [myClass theNonMetaClass inspectAllInstances].
  12351. ! !
  12352.  
  12353. !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:02'!
  12354. inspectSubInstances
  12355.     "Inspect all instances of the selected class and all its subclasses  1/26/96 sw"
  12356.  
  12357.     | aClass |
  12358.     aClass _ self selectedClassOrMetaClass.
  12359.     aClass ~~ nil ifTrue:
  12360.         [aClass _ aClass theNonMetaClass.
  12361.          aClass inspectSubInstances].
  12362. ! !
  12363.  
  12364. !Browser methodsFor: 'message functions' stamp: 'tk 4/18/1998 16:14'!
  12365. messageListMenu: aMenu shifted: shifted
  12366.     ^ shifted ifFalse: [aMenu labels:
  12367. 'browse full
  12368. fileOut
  12369. printOut
  12370. senders of...
  12371. implementors of...
  12372. method inheritance
  12373. versions
  12374. inst var refs...
  12375. inst var defs...
  12376. class var refs...
  12377. class variables
  12378. class refs
  12379. remove
  12380. more...'
  12381.     lines: #(3 7 12)
  12382.     selections:
  12383.         #(browseMethodFull fileOutMessage printOutMessage
  12384.         browseSendersOfMessages browseMessages methodHierarchy browseVersions
  12385.         browseInstVarRefs browseInstVarDefs browseClassVarRefs 
  12386.             browseClassVariables browseClassRefs
  12387.         removeMessage shiftedYellowButtonActivity )]
  12388.  
  12389.     ifTrue: [aMenu labels: 'browse class hierarchy
  12390. browse class
  12391. browse method
  12392. implementors of sent messages
  12393. change sets with this method
  12394. inspect instances
  12395. inspect subinstances
  12396. remove from this browser
  12397. revert to previous version
  12398. remove from current change set
  12399. revert and forget
  12400. more...' 
  12401.     lines: #(5 7 11)
  12402.     selections: #(classHierarchy browseClass 
  12403.         buildMessageBrowser browseAllMessages findMethodInChangeSets 
  12404.         inspectInstances inspectSubInstances
  12405.         removeMessageFromBrowser revertToPreviousVersion 
  12406.         removeFromCurrentChanges revertAndForget
  12407.         unshiftedYellowButtonActivity)]
  12408. ! !
  12409.  
  12410. !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:03'!
  12411. removeFromCurrentChanges
  12412.     "Tell the changes mgr to forget that the current msg was changed."
  12413.  
  12414.     Smalltalk changes removeSelectorChanges: self selectedMessageName 
  12415.             class: self selectedClassOrMetaClass.
  12416. ! !
  12417.  
  12418. !Browser methodsFor: 'message functions' stamp: 'tk 4/25/1998 00:07'!
  12419. removeMessage
  12420.     "If a message is selected, create a Confirmer so the user can verify that 
  12421.     the currently selected message should be removed from the system. If so, 
  12422.     remove it.  If the Preference 'confirmMethodRemoves' is set to false, the 
  12423.     confirmer is bypassed."
  12424.     | messageName confirmation |
  12425.  
  12426.     messageListIndex = 0 ifTrue: [^ self].
  12427.     self okToChange ifFalse: [^ self].
  12428.     messageName _ self selectedMessageName.
  12429.     confirmation _ self selectedClassOrMetaClass confirmRemovalOf: messageName.
  12430.     confirmation == 3 ifTrue: [^ self].
  12431.  
  12432.     self selectedClassOrMetaClass removeSelector: self selectedMessageName.
  12433.     self changed: #messageList.
  12434.     self messageListIndex: 0.
  12435.     self setClassOrganizer.  "In case organization not cached"
  12436.  
  12437.     confirmation == 2 ifTrue:
  12438.         [Smalltalk browseAllCallsOn: messageName]
  12439. ! !
  12440.  
  12441. !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:03'!
  12442. removeMessageFromBrowser
  12443.     "Our list speaks the truth and can't have arbitrary things removed"
  12444.  
  12445.     ^ self changed: #flash! !
  12446.  
  12447. !Browser methodsFor: 'message functions' stamp: 'tk 4/24/1998 23:46'!
  12448. revertAndForget
  12449.     "Revert to the previous version of the current method, and tell the changes mgr to forget that it was ever changed.  Danger!!  Use only if you really know what you're doing!!"
  12450.  
  12451.     self revertToPreviousVersion.
  12452.     self removeFromCurrentChanges.
  12453.     self changed: #contents! !
  12454.  
  12455. !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 17:04'!
  12456. revertToPreviousVersion
  12457.     "Revert to the previous version of the current method"
  12458.  
  12459.     | aClass aSelector  changeRecords codeController |
  12460.     aClass _ self selectedClassOrMetaClass.
  12461.     aClass ifNil: [^ self changed: #flash].
  12462.     aSelector _ self selectedMessageName.
  12463.     changeRecords _ aClass changeRecordsAt: aSelector.
  12464.     changeRecords size <= 1 ifTrue: [self changed: #flash.  ^ self beep].
  12465.     codeController _ (self dependents detect: [:v | v isKindOf: PluggableTextView]) controller.
  12466.         "later find a better way to do this!!"
  12467.     self contents: (changeRecords at: 2) string notifying: codeController.
  12468.     self changed: #contents! !
  12469.  
  12470. !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 20:57'!
  12471. shiftedYellowButtonActivity
  12472.     "Invoke the model's other menu.  Just do what the controller would have done."
  12473.  
  12474.     | menu |
  12475.     menu _ self messageListMenu: (CustomMenu new) shifted: true.
  12476.     menu == nil
  12477.         ifTrue: [Sensor waitNoButton]
  12478.         ifFalse: [menu invokeOn: self].
  12479. ! !
  12480.  
  12481. !Browser methodsFor: 'message functions' stamp: 'tk 4/2/98 20:58'!
  12482. unshiftedYellowButtonActivity
  12483.     "Invoke the model's other menu.  Just do what the controller would have done."
  12484.  
  12485.     | menu |
  12486.     menu _ self messageListMenu: (CustomMenu new) shifted: false.
  12487.     menu == nil
  12488.         ifTrue: [Sensor waitNoButton]
  12489.         ifFalse: [menu invokeOn: self].
  12490. ! !
  12491.  
  12492.  
  12493. !Browser methodsFor: 'code pane' stamp: 'tk 4/9/98 14:03'!
  12494. showBytecodes
  12495.     "Show the bytecodes of the selected method."
  12496.     "Set a mode for contents!!"
  12497.  
  12498.     ((self messageListIndex = 0) | (self okToChange not))
  12499.         ifTrue: [^ self changed: #flash].
  12500.     editSelection _ #byteCodes.
  12501.     self changed: #contents.
  12502. ! !
  12503.  
  12504.  
  12505. !Browser methodsFor: 'metaclass' stamp: 'di 1/14/98 12:25'!
  12506. classCommentIndicated
  12507.     "Answer true iff we're viewing the class comment."
  12508.  
  12509.     ^ editSelection == #editComment 
  12510. ! !
  12511.  
  12512. !Browser methodsFor: 'metaclass'!
  12513. classMessagesIndicated
  12514.     "Answer whether the messages to be presented should come from the 
  12515.     metaclass."
  12516.  
  12517.     ^ self metaClassIndicated! !
  12518.  
  12519. !Browser methodsFor: 'metaclass'!
  12520. classOrMetaClassOrganizer
  12521.     "Answer the class organizer for the metaclass or class, depending on 
  12522.     which (instance or class) is indicated."
  12523.  
  12524.     self metaClassIndicated
  12525.         ifTrue: [^metaClassOrganizer]
  12526.         ifFalse: [^classOrganizer]! !
  12527.  
  12528. !Browser methodsFor: 'metaclass'!
  12529. indicateClassMessages
  12530.     "Indicate that the message selection should come from the metaclass 
  12531.     messages."
  12532.  
  12533.     self metaClassIndicated: true! !
  12534.  
  12535. !Browser methodsFor: 'metaclass'!
  12536. indicateInstanceMessages
  12537.     "Indicate that the message selection should come from the class (instance) 
  12538.     messages."
  12539.  
  12540.     self metaClassIndicated: false! !
  12541.  
  12542. !Browser methodsFor: 'metaclass' stamp: 'di 1/14/98 13:20'!
  12543. instanceMessagesIndicated
  12544.     "Answer whether the messages to be presented should come from the 
  12545.     class."
  12546.  
  12547.     ^metaClassIndicated not and: [self classCommentIndicated not]! !
  12548.  
  12549. !Browser methodsFor: 'metaclass' stamp: 'di 1/14/98 13:19'!
  12550. metaClassIndicated
  12551.     "Answer the boolean flag that indicates which of the method dictionaries, 
  12552.     class or metaclass."
  12553.  
  12554.     ^ metaClassIndicated and: [self classCommentIndicated not]! !
  12555.  
  12556. !Browser methodsFor: 'metaclass' stamp: 'tk 4/2/98 17:05'!
  12557. metaClassIndicated: trueOrFalse 
  12558.     "Indicate whether browsing instance or class messages."
  12559.     metaClassIndicated _ trueOrFalse.
  12560.     self setClassOrganizer.
  12561.     systemCategoryListIndex > 0 ifTrue:
  12562.         [editSelection _ classListIndex = 0
  12563.             ifTrue: [metaClassIndicated
  12564.                 ifTrue: [#none]
  12565.                 ifFalse: [#newClass]]
  12566.             ifFalse: [#editClass]].
  12567.     messageCategoryListIndex _ 0.
  12568.     messageListIndex _ 0.
  12569.     contents _ nil.
  12570.     self changed: #classSelectionChanged.
  12571.     self changed: #messageCategoryList.
  12572.     self changed: #messageList.
  12573.     self changed: #contents.
  12574. ! !
  12575.  
  12576. !Browser methodsFor: 'metaclass' stamp: 'tk 4/9/98 10:48'!
  12577. selectedClassOrMetaClass
  12578.     "Answer the selected class or metaclass."
  12579.  
  12580.     | cls |
  12581.     self metaClassIndicated
  12582.         ifTrue: [^ (cls _ self selectedClass) ifNil: [nil] ifNotNil: [cls class]]
  12583.         ifFalse: [^ self selectedClass]! !
  12584.  
  12585. !Browser methodsFor: 'metaclass'!
  12586. selectedClassOrMetaClassName
  12587.     "Answer the selected class name or metaclass name."
  12588.  
  12589.     ^self selectedClassOrMetaClass name! !
  12590.  
  12591. !Browser methodsFor: 'metaclass' stamp: 'di 1/14/98 13:27'!
  12592. setClassOrganizer
  12593.     "Install whatever organization is appropriate"
  12594.     | theClass |
  12595.     classOrganizer _ nil.
  12596.     metaClassOrganizer _ nil.
  12597.     classListIndex = 0 ifTrue: [^ self].
  12598.     classOrganizer _ (theClass _ self selectedClass) organization.
  12599.     metaClassOrganizer _ theClass class organization.! !
  12600.  
  12601. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  12602.  
  12603. Browser class
  12604.     instanceVariableNames: ''!
  12605.  
  12606. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/10/1998 17:37'!
  12607. fullOnClass: aClass 
  12608.     "Open a new full browser set to class."
  12609.     | brow |
  12610.     brow _ Browser new.
  12611.     brow setClass: aClass selector: nil.
  12612.     Browser openBrowserView: (brow openEditString: nil)
  12613.         label: 'System Browser'! !
  12614.  
  12615. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/18/1998 15:27'!
  12616. fullOnClass: aClass selector: aSelector
  12617.     "Open a new full browser set to class."
  12618.  
  12619.     | brow |
  12620.     brow _ Browser new.
  12621.     brow setClass: aClass selector: aSelector.
  12622.     Browser openBrowserView: (brow openEditString: nil)
  12623.         label: 'System Browser'! !
  12624.  
  12625. !Browser class methodsFor: 'instance creation'!
  12626. new
  12627.  
  12628.     ^super new systemOrganizer: SystemOrganization! !
  12629.  
  12630. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/6/98 22:04'!
  12631. newOnCategory: aCategory
  12632.     "Browse the system category of the given name.  7/13/96 sw"
  12633.  
  12634.     "Browser newOnCategory: 'Interface-Browser'"
  12635.  
  12636.     | newBrowser catList |
  12637.     newBrowser _ Browser new.
  12638.     catList _ newBrowser systemCategoryList.
  12639.     newBrowser systemCategoryListIndex: 
  12640.         (catList indexOf: aCategory asSymbol ifAbsent: [^ self inform: 'No such category']).
  12641.     Browser openBrowserView: (newBrowser openSystemCatEditString: nil)
  12642.                 label: 'Classes in category ', aCategory
  12643. ! !
  12644.  
  12645. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/18/1998 16:28'!
  12646. newOnClass: aClass 
  12647.     "Open a new class browser on this class."
  12648.     ^ self newOnClass: aClass label: 'Class Browser: ', aClass name! !
  12649.  
  12650. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/6/98 22:55'!
  12651. newOnClass: aClass label: aLabel
  12652.     "Open a new class browser on this class."
  12653.     | newBrowser |
  12654.  
  12655.     newBrowser _ Browser new.
  12656.     newBrowser setClass: aClass selector: nil.
  12657.     Browser openBrowserView: (newBrowser openOnClassWithEditString: nil)
  12658.             label: aLabel
  12659. ! !
  12660.  
  12661. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/18/1998 16:29'!
  12662. newOnClass: aClass selector: aSymbol
  12663.     "Open a new class browser on this class."
  12664.     | newBrowser |
  12665.  
  12666.     newBrowser _ Browser new.
  12667.     newBrowser setClass: aClass selector: aSymbol.
  12668.     Browser openBrowserView: (newBrowser openOnClassWithEditString: nil)
  12669.             label: 'Class Browser: ', aClass name
  12670. ! !
  12671.  
  12672. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/6/98 21:28'!
  12673. openBrowser
  12674.     "Create and schedule a BrowserView with label 'System Browser'. The 
  12675.     view consists of five subviews, starting with the list view of system 
  12676.     categories of SystemOrganization. The initial text view part is empty."
  12677.  
  12678.     Browser openBrowserView: (Browser new openEditString: nil)
  12679.             label: 'System Browser'
  12680. ! !
  12681.  
  12682. !Browser class methodsFor: 'instance creation' stamp: 'di 5/14/1998 09:43'!
  12683. openBrowserView: aBrowserView label: aString 
  12684.     "Schedule aBrowserView, labelling the view aString."
  12685.     
  12686.     aBrowserView isMorph
  12687.         ifTrue:  [(aBrowserView setLabel: aString) openInWorld]
  12688.         ifFalse: [aBrowserView label: aString.
  12689.                 aBrowserView minimumSize: 300 @ 200.
  12690.                 aBrowserView subViews do: [:each | each controller].
  12691.                 aBrowserView controller open]! !
  12692.  
  12693. !Browser class methodsFor: 'instance creation' stamp: 'tk 4/6/98 21:44'!
  12694. openMessageBrowserForClass: aBehavior selector: aSymbol editString: aString
  12695.     "Create and schedule a message browser for the class, aBehavior, in 
  12696.     which the argument, aString, contains characters to be edited in the text 
  12697.     view. These characters are the source code for the message selector 
  12698.     aSymbol."
  12699.  
  12700.     | newBrowser |
  12701.     (newBrowser _ Browser new) setClass: aBehavior selector: aSymbol.
  12702.     ^ Browser openBrowserView: (newBrowser openMessageEditString: aString)
  12703.         label: newBrowser selectedClassOrMetaClassName , ' ' , newBrowser selectedMessageName
  12704. ! !
  12705.  
  12706.  
  12707. !Browser class methodsFor: 'class initialization'!
  12708. initialize
  12709.         "Browser initialize"
  12710.  
  12711.         RecentClasses := OrderedCollection new! !
  12712. Switch subclass: #Button
  12713.     instanceVariableNames: ''
  12714.     classVariableNames: ''
  12715.     poolDictionaries: ''
  12716.     category: 'Interface-Menus'!
  12717. !Button commentStamp: 'di 5/22/1998 16:32' prior: 0!
  12718. Button comment:
  12719. 'I am a Switch that turns off automatically after being turned on, that is, I act like a push-button switch.'!
  12720.  
  12721.  
  12722. !Button methodsFor: 'state'!
  12723. turnOff
  12724.     "Sets the state of the receiver to 'off'. The off action of the receiver is not  
  12725.     executed."
  12726.  
  12727.     on _ false! !
  12728.  
  12729. !Button methodsFor: 'state'!
  12730. turnOn
  12731.     "The receiver remains in the 'off' state'."
  12732.  
  12733.     self doAction: onAction.
  12734.     self doAction: offAction! !
  12735.  
  12736. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  12737.  
  12738. Button class
  12739.     instanceVariableNames: ''!
  12740.  
  12741. !Button class methodsFor: 'instance creation'!
  12742. newOn 
  12743.     "Refer to the comment in Switch|newOn."
  12744.  
  12745.     self error: 'Buttons cannot be created in the on state'.
  12746.     ^nil! !
  12747. SimpleButtonMorph subclass: #ButtonMorph
  12748.     instanceVariableNames: 'lastAcceptedScript lastScriptEditor '
  12749.     classVariableNames: ''
  12750.     poolDictionaries: ''
  12751.     category: 'Experimental-Miscellaneous'!
  12752.  
  12753. !ButtonMorph methodsFor: 'menu' stamp: 'di 11/4/97 09:01'!
  12754. addCustomMenuItems: aCustomMenu hand: aHandMorph
  12755.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  12756.     aCustomMenu add: 'border color' action: #changeBorderColor:.
  12757.     aCustomMenu add: 'border width' action: #changeBorderWidth:.
  12758.     aCustomMenu add: 'change label' action: #setLabel.
  12759.     aCustomMenu add: 'script' action: #editScript:.
  12760. ! !
  12761.  
  12762. !ButtonMorph methodsFor: 'menu'!
  12763. editScript: evt
  12764.  
  12765.     self nameInModel ifNil: [self choosePartNameSilently].
  12766.     evt hand attachMorph:
  12767.         (self scriptEditorFor: 'buttonUp').
  12768. ! !
  12769.  
  12770. !ButtonMorph methodsFor: 'menu'!
  12771. hasScript
  12772.     "Return true if there is already a script for this morph."
  12773.  
  12774.     ^ lastAcceptedScript ~~ nil! !
  12775.  
  12776. !ButtonMorph methodsFor: 'menu'!
  12777. scriptEditorFor: ignored
  12778.  
  12779.     (lastScriptEditor ~= nil and: [lastScriptEditor isInWorld])
  12780.         ifTrue: [^ lastScriptEditor].
  12781.  
  12782.     lastAcceptedScript = nil ifTrue: [
  12783.         ^ lastScriptEditor _ ScriptEditorMorph new
  12784.             setMorph: self
  12785.             scriptName: 'ButtonUp'.
  12786.     ] ifFalse: [
  12787.         ^ lastScriptEditor _ lastAcceptedScript fullCopy].
  12788. ! !
  12789.  
  12790.  
  12791. !ButtonMorph methodsFor: 'copying' stamp: 'tk 12/4/97 11:22'!
  12792. copy
  12793.  
  12794.     | obj |
  12795.     obj _ super copy.
  12796.     obj lastScriptEditor: obj lastAcceptedScript.    
  12797.         "lastScriptEditor would not have been copied, as it is owned by the world, not me.  Can't allow mine to creep into the copy." 
  12798.     ^ obj! !
  12799.  
  12800. !ButtonMorph methodsFor: 'copying' stamp: 'sw 9/22/97 08:57'!
  12801. copyRecordingIn: dict
  12802.     "Overridden to copy lastAcceptedScript as well."
  12803.  
  12804.     | new |
  12805.     new _ super copyRecordingIn: dict.
  12806.     lastAcceptedScript ifNotNil: [
  12807.         new lastAcceptedScript: 
  12808.             ((dict includesKey: lastAcceptedScript)
  12809.                 ifTrue: [dict at: lastAcceptedScript]
  12810.                 ifFalse: [lastAcceptedScript copyRecordingIn: dict])].
  12811.     lastScriptEditor ifNotNil: [
  12812.         new lastScriptEditor: 
  12813.             ((dict includesKey: lastScriptEditor)
  12814.                 ifTrue: [dict at: lastScriptEditor]
  12815.                 ifFalse: [lastScriptEditor copyRecordingIn: dict])].
  12816.     ^ new
  12817. ! !
  12818.  
  12819. !ButtonMorph methodsFor: 'copying' stamp: 'tk 12/4/97 11:23'!
  12820. prepareToBeSaved
  12821.     "SmartRefStream will not write any morph that is owned by someone outside the root being written.  (See DataStream.typeIDFor:)  Open Scripts are like that.  Make a private copy of the scriptEditor."
  12822.  
  12823.     super prepareToBeSaved.
  12824.     lastAcceptedScript ifNotNil: [
  12825.         lastAcceptedScript owner ifNotNil: ["open on the screen"
  12826.             lastAcceptedScript _ lastAcceptedScript fullCopy setMorph: self.
  12827.             "lastAcceptedScript privateOwner: nil" "fullCopy does it"]].
  12828.     "lastScriptEditor will not be written out"! !
  12829.  
  12830. !ButtonMorph methodsFor: 'copying' stamp: 'tk 12/4/97 11:21'!
  12831. shallowCopy
  12832.  
  12833.     | obj |
  12834.     obj _ super shallowCopy.
  12835.     obj lastScriptEditor: obj lastAcceptedScript.    
  12836.         "lastScriptEditor would not have been copied, as it is owned by the world, not me.  Can't allow mine to creep into the copy." 
  12837.     ^ obj! !
  12838.  
  12839.  
  12840. !ButtonMorph methodsFor: 'other'!
  12841. acceptScript: aScriptEditorMorph for: ignored
  12842.  
  12843.     lastAcceptedScript _ aScriptEditorMorph.
  12844.     self world model class
  12845.         compile: lastAcceptedScript methodString
  12846.         classified: 'scripts'
  12847.         notifying: nil.
  12848. ! !
  12849.  
  12850. !ButtonMorph methodsFor: 'other'!
  12851. buttonUpSelector
  12852.  
  12853.     ^ (self nameInModel, 'ButtonUp') asSymbol
  12854. ! !
  12855.  
  12856. !ButtonMorph methodsFor: 'other'!
  12857. choosePartName
  12858.     "Override to add null on-ticks script when this morph is named."
  12859.  
  12860.     | newName |
  12861.     newName _ super choosePartName.
  12862.     newName ifNil: [^ self].  "user cancelled or chose a bad part name"
  12863.     (self world model class)
  12864.         compile: self buttonUpSelector
  12865.         classified: 'scripts'
  12866.         notifying: nil.
  12867. ! !
  12868.  
  12869. !ButtonMorph methodsFor: 'other'!
  12870. choosePartNameSilently
  12871.  
  12872.     super choosePartNameSilently.
  12873.     (self world model class)
  12874.         compile: self buttonUpSelector
  12875.         classified: 'scripts'
  12876.         notifying: nil.
  12877. ! !
  12878.  
  12879. !ButtonMorph methodsFor: 'other'!
  12880. doButtonAction
  12881.  
  12882.     self nameInModel ~~ nil ifTrue: [
  12883.         self world model perform: self buttonUpSelector].
  12884. ! !
  12885.  
  12886. !ButtonMorph methodsFor: 'other' stamp: 'tk 12/4/97 11:22'!
  12887. lastAcceptedScript
  12888.     ^ lastAcceptedScript! !
  12889.  
  12890. !ButtonMorph methodsFor: 'other' stamp: 'tk 9/21/97 00:16'!
  12891. lastAcceptedScript: scriptEditor
  12892.     "Need to do a clean store here."
  12893.  
  12894.     lastAcceptedScript _ scriptEditor! !
  12895.  
  12896. !ButtonMorph methodsFor: 'other' stamp: 'tk 9/21/97 00:16'!
  12897. lastScriptEditor: scriptEditor
  12898.     "Need to do a clean store here."
  12899.  
  12900.     lastScriptEditor _ scriptEditor! !
  12901. ArrayedCollection variableByteSubclass: #ByteArray
  12902.     instanceVariableNames: ''
  12903.     classVariableNames: ''
  12904.     poolDictionaries: ''
  12905.     category: 'Collections-Arrayed'!
  12906. !ByteArray commentStamp: 'di 5/22/1998 16:32' prior: 0!
  12907. ByteArray comment:
  12908. 'I represent an ArrayedCollection whose elements can only be integers between 0 and 255. They are stored two bytes to a word.'!
  12909.  
  12910.  
  12911. !ByteArray methodsFor: 'accessing'!
  12912. asString
  12913.     "Convert to a String with Characters for each byte.
  12914.     Fast code uses primitive that avoids character conversion"
  12915.  
  12916.     ^ (String new: self size) replaceFrom: 1 to: self size with: self! !
  12917.  
  12918. !ByteArray methodsFor: 'accessing'!
  12919. doubleWordAt: i 
  12920.     "Answer the value of the double word (4 bytes) starting at byte index i."
  12921.  
  12922.     | b0 b1 b2 w |
  12923.     "Primarily for reading socket #s in Pup headers"
  12924.     b0 _ self at: i.  
  12925.     b1 _ self at: i+1.  
  12926.     b2 _ self at: i+2.  
  12927.     w _ self at: i+3.
  12928.     "Following sequence minimizes LargeInteger arithmetic for small results."
  12929.     b2=0 ifFalse: [w _ (b2 bitShift: 8) + w].
  12930.     b1=0 ifFalse: [w _ (b1 bitShift: 16) + w].
  12931.     b0=0 ifFalse: [w _ (b0 bitShift: 24) + w].
  12932.     ^w! !
  12933.  
  12934. !ByteArray methodsFor: 'accessing'!
  12935. doubleWordAt: i put: value 
  12936.     "Set the value of the double word (4 bytes) starting at byte index i."
  12937.  
  12938.     | w |
  12939.     "Primarily for setting socket #s in Pup headers"
  12940.     w _ value asInteger.
  12941.     self at: i put: (w digitAt: 4).
  12942.     self at: i + 1 put: (w digitAt: 3).
  12943.     self at: i + 2 put: (w digitAt: 2).
  12944.     self at: i + 3 put: (w digitAt: 1)! !
  12945.  
  12946. !ByteArray methodsFor: 'accessing'!
  12947. wordAt: i 
  12948.     "Answer the value of the word (2 bytes) starting at index i."
  12949.  
  12950.     | j |
  12951.     j _ i + i.
  12952.     ^((self at: j - 1) bitShift: 8) + (self at: j)! !
  12953.  
  12954. !ByteArray methodsFor: 'accessing'!
  12955. wordAt: i put: v 
  12956.     "Set the value of the word (2 bytes) starting at index i."
  12957.  
  12958.     | j |
  12959.     j _ i + i.
  12960.     self at: j - 1 put: ((v bitShift: -8) bitAnd: 8r377).
  12961.     self at: j put: (v bitAnd: 8r377)! !
  12962.  
  12963.  
  12964. !ByteArray methodsFor: 'private'!
  12965. defaultElement
  12966.  
  12967.     ^0! !
  12968.  
  12969. !ByteArray methodsFor: 'private'!
  12970. replaceFrom: start to: stop with: replacement startingAt: repStart 
  12971.     "Primitive. This destructively replaces elements from start to stop in the receiver starting at index, repStart, in the collection, replacement. Answer the receiver. Range checks are performed in the primitive only. Optional. See Object documentation whatIsAPrimitive."
  12972.     <primitive: 105>
  12973.     super replaceFrom: start to: stop with: replacement startingAt: repStart! !
  12974. Object subclass: #CCodeGenerator
  12975.     instanceVariableNames: 'translationDict inlineList constants variables variableDeclarations methods variablesSetCache '
  12976.     classVariableNames: ''
  12977.     poolDictionaries: ''
  12978.     category: 'Squeak-Translation to C'!
  12979. !CCodeGenerator commentStamp: 'di 5/22/1998 16:32' prior: 0!
  12980. CCodeGenerator comment:
  12981. 'This class oversees the translation of a subset of Smalltalk to C, allowing the comforts of Smalltalk during development and the efficiency and portability of C for the resulting interpreter.  Executing
  12982.  
  12983.     Interpreter translate: ''InterpTest.c'' doInlining: true.
  12984.  
  12985. (with single quotes) will cause all the methods of Interpreter, ObjectMemory and BitBltSimulation to be translated to C, and stored in the named file.  This file together with the files emitted by InterpreterSupportCode (qv) should be adequate to produce a complete interpreter for the Macintosh environment.'!
  12986.  
  12987.  
  12988. !CCodeGenerator methodsFor: 'public' stamp: 'ikp 12/4/97 23:01'!
  12989. addClass: aClass
  12990.     "Add the variables and methods of the given class to the code base."
  12991.     | source |
  12992.     self checkClassForNameConflicts: aClass.
  12993.     aClass classPool associationsDo: [ :assoc |
  12994.         constants at: assoc key put: (TConstantNode new setValue: assoc value).
  12995.     ].
  12996.     "ikp..."
  12997.     aClass sharedPools do: [:pool |
  12998.         pool associationsDo: [ :assoc |
  12999.             constants at: assoc key put: (TConstantNode new setValue: assoc value).
  13000.         ].
  13001.     ].
  13002.     variables addAll: aClass instVarNames.
  13003. 'Adding Class ' , aClass name , '...'
  13004. displayProgressAt: Sensor cursorPoint
  13005. from: 0 to: aClass selectors size
  13006. during: [:bar |
  13007.     aClass selectors doWithIndex: [ :sel :i | bar value: i.
  13008.         source _ aClass sourceCodeAt: sel.
  13009.         self addMethod: ((Compiler new parse: source in: aClass notifying: nil) asTMethodFromClass: aClass).
  13010.     ]].! !
  13011.  
  13012. !CCodeGenerator methodsFor: 'public' stamp: 'jm 1/5/98 16:36'!
  13013. addClassVarsFor: aClass
  13014.     "Add the class variables for the given class (and its superclasses) to the code base as constants."
  13015.  
  13016.     | allClasses |
  13017.     allClasses _ aClass allSuperclasses asOrderedCollection.
  13018.     allClasses add: aClass.
  13019.     allClasses do: [:c |
  13020.         c classPool associationsDo:
  13021.             [:assoc | constants at: assoc key put: (TConstantNode new setValue: assoc value)]].
  13022. ! !
  13023.  
  13024. !CCodeGenerator methodsFor: 'public' stamp: 'ikp 9/26/97 14:48'!
  13025. codeString
  13026.     "Return a string containing all the C code for the code base. Used for testing."
  13027.  
  13028.     | stream |
  13029.     stream _ ReadWriteStream on: (String new: 1000).
  13030.     self emitCCodeOn: stream doInlining: true doAssertions: true.
  13031.     ^stream contents! !
  13032.  
  13033. !CCodeGenerator methodsFor: 'public' stamp: 'jm 2/15/98 18:26'!
  13034. codeStringForPrimitives: classAndSelectorList
  13035.  
  13036.     | sel aClass source s verbose meth |
  13037.     self initialize.
  13038.     classAndSelectorList do: [:classAndSelector |
  13039.         aClass _ Smalltalk at: (classAndSelector at: 1).
  13040.         self addClassVarsFor: aClass.
  13041.         sel _ classAndSelector at: 2.
  13042.         (aClass includesSelector: sel)
  13043.             ifTrue: [source _ aClass sourceCodeAt: sel]
  13044.             ifFalse: [source _ aClass class sourceCodeAt: sel].
  13045.         meth _ ((Compiler new parse: source in: aClass notifying: nil)
  13046.                 asTMethodFromClass: aClass).
  13047.         meth primitive > 0 ifTrue: [meth preparePrimitiveInClass: aClass].
  13048.         "for old-style array accessing:
  13049.             meth covertToZeroBasedArrayReferences."
  13050.         meth replaceSizeMessages.
  13051.         self addMethod: meth].
  13052.  
  13053.     "method preparation"
  13054.     verbose _ false.
  13055.     self prepareMethods.
  13056.     verbose ifTrue: [
  13057.         self printUnboundCallWarnings.
  13058.         self printUnboundVariableReferenceWarnings.
  13059.         Transcript cr].
  13060.  
  13061.     "code generation"
  13062.     self doInlining: true.
  13063.     s _ ReadWriteStream on: (String new: 1000).
  13064.     methods _ methods asSortedCollection: [:m1 :m2 | m1 selector < m2 selector].
  13065.     self emitCHeaderForPrimitivesOn: s.
  13066.     self emitCVariablesOn: s.
  13067.     self emitCFunctionPrototypesOn: s.
  13068.     methods do: [:m | m emitCCodeOn: s generator: self].
  13069.     ^ s contents
  13070. ! !
  13071.  
  13072. !CCodeGenerator methodsFor: 'public'!
  13073. globalsAsSet
  13074.     "Used by the inliner to avoid name clashes with global variables."
  13075.  
  13076.     ((variablesSetCache == nil) or:
  13077.      [variablesSetCache size ~= variables size]) ifTrue: [
  13078.         variablesSetCache _ variables asSet.
  13079.     ].
  13080.     ^ variablesSetCache! !
  13081.  
  13082. !CCodeGenerator methodsFor: 'public'!
  13083. initialize
  13084.  
  13085.     translationDict _ Dictionary new.
  13086.     inlineList _ Array new.
  13087.     constants _ Dictionary new.
  13088.     variables _ OrderedCollection new.
  13089.     variableDeclarations _ Dictionary new.
  13090.     methods _ Dictionary new.
  13091.     self initializeCTranslationDictionary.! !
  13092.  
  13093. !CCodeGenerator methodsFor: 'public' stamp: 'ikp 9/26/97 14:50'!
  13094. storeCodeOnFile: fileName doInlining: inlineFlag
  13095.     "Store C code for this code base on the given file."
  13096.  
  13097.     self storeCodeOnFile: fileName doInlining: inlineFlag doAssertions: true! !
  13098.  
  13099. !CCodeGenerator methodsFor: 'public' stamp: 'ikp 9/26/97 14:50'!
  13100. storeCodeOnFile: fileName doInlining: inlineFlag doAssertions: assertionFlag
  13101.     "Store C code for this code base on the given file."
  13102.  
  13103.     | stream |
  13104.     stream _ FileStream newFileNamed: fileName.
  13105.     self emitCCodeOn: stream doInlining: inlineFlag doAssertions: assertionFlag.
  13106.     stream close.! !
  13107.  
  13108. !CCodeGenerator methodsFor: 'public'!
  13109. var: varName declareC: declarationString
  13110.     "Record the given C declaration for a global variable."
  13111.  
  13112.     variableDeclarations at: varName put: declarationString.! !
  13113.  
  13114.  
  13115. !CCodeGenerator methodsFor: 'error notification' stamp: 'ikp 12/4/97 22:56'!
  13116. checkClassForNameConflicts: aClass
  13117.     "Verify that the given class does not have constant, variable, or method names that conflict with those of previously added classes. Raise an error if a conflict is found, otherwise just return."
  13118.  
  13119.     "check for constant name collisions"
  13120.     aClass classPool associationsDo: [ :assoc |
  13121.         (constants includesKey: assoc key) ifTrue: [
  13122.             self error: 'Constant was defined in a previously added class: ', assoc key.
  13123.         ].
  13124.     ].
  13125.     "ikp..."
  13126.     aClass sharedPools do: [:pool |
  13127.         pool associationsDo: [ :assoc |
  13128.             (constants includesKey: assoc key) ifTrue: [
  13129.                 self error: 'Constant was defined in a previously added class: ', assoc key.
  13130.             ].
  13131.         ].
  13132.     ].
  13133.  
  13134.     "check for instance variable name collisions"
  13135.     aClass instVarNames do: [ :varName |
  13136.         (variables includes: varName) ifTrue: [
  13137.             self error: 'Instance variable was defined in a previously added class: ', varName.
  13138.         ].
  13139.     ].
  13140.  
  13141.     "check for method name collisions"
  13142.     aClass selectors do: [ :sel |
  13143.         (methods includesKey: sel) ifTrue: [
  13144.             self error: 'Method was defined in a previously added class: ', sel.
  13145.         ].
  13146.     ].! !
  13147.  
  13148. !CCodeGenerator methodsFor: 'error notification'!
  13149. printUnboundCallWarnings
  13150.     "Print a warning message for every unbound method call in the code base."
  13151.  
  13152.     | knownSelectors undefinedCalls |
  13153.     undefinedCalls _ Dictionary new.
  13154.     knownSelectors _ translationDict keys asSet.
  13155.     knownSelectors add: #error:.
  13156.     methods do: [ :m | knownSelectors add: m selector ].
  13157.     methods do: [ :m |
  13158.         m allCalls do: [ :sel |
  13159.             (knownSelectors includes: sel) ifFalse: [
  13160.                 (undefinedCalls includesKey: sel)
  13161.                     ifTrue: [ (undefinedCalls at: sel) add: m selector ]
  13162.                     ifFalse: [ undefinedCalls at: sel put: (OrderedCollection with: m selector) ].
  13163.             ].
  13164.         ].
  13165.     ].
  13166.  
  13167.     Transcript cr.
  13168.     undefinedCalls keys asSortedCollection do: [ :undefined |
  13169.         Transcript show: undefined, ' -- undefined method sent by:'; cr.
  13170.         (undefinedCalls at: undefined) do: [ :caller |
  13171.             Transcript tab; show: caller; cr.
  13172.         ].
  13173.     ].! !
  13174.  
  13175. !CCodeGenerator methodsFor: 'error notification'!
  13176. printUnboundVariableReferenceWarnings
  13177.     "Print a warning message for every unbound variable reference in the code base."
  13178.  
  13179.     | undefinedRefs globalVars knownVars |
  13180.     undefinedRefs _ Dictionary new.
  13181.     globalVars _ Set new: 100.
  13182.     globalVars addAll: variables.
  13183.     methods do: [ :m |
  13184.         knownVars _ globalVars copy.
  13185.         m args do: [ :var | knownVars add: var ].
  13186.         m locals do: [ :var | knownVars add: var ].
  13187.         m freeVariableReferences do: [ :varName |
  13188.             (knownVars includes: varName) ifFalse: [
  13189.                 (undefinedRefs includesKey: varName)
  13190.                     ifTrue: [ (undefinedRefs at: varName) add: m selector ]
  13191.                     ifFalse: [ undefinedRefs at: varName put: (OrderedCollection with: m selector) ].
  13192.             ].
  13193.         ].
  13194.     ].
  13195.  
  13196.     Transcript cr.
  13197.     undefinedRefs keys asSortedCollection do: [ :var |
  13198.         Transcript show: var, ' -- undefined variable used in:'; cr.
  13199.         (undefinedRefs at: var) do: [ :sel |
  13200.             Transcript tab; show: sel; cr.
  13201.         ].
  13202.     ].! !
  13203.  
  13204.  
  13205. !CCodeGenerator methodsFor: 'inlining'!
  13206. collectInlineList
  13207.     "Make a list of methods that should be inlined."
  13208.     "Details: The method must not include any inline C, since the translator cannot currently map variable names in inlined C code. Methods to be inlined must be small or called from only one place."
  13209.  
  13210.     | methodsNotToInline callsOf inlineIt hasCCode nodeCount senderCount |
  13211.     methodsNotToInline _ Set new: methods size.
  13212.  
  13213.     "build dictionary to record the number of calls to each method"
  13214.     callsOf _ Dictionary new: methods size * 2.
  13215.     methods keys do: [ :sel | callsOf at: sel put: 0 ].
  13216.  
  13217.     "For each method, scan its parse tree once to:
  13218.         1. determine if the method contains C code or declarations
  13219.         2. determine how many nodes it has
  13220.         3. increment the sender counts of the methods it calls
  13221.         4. determine if it includes any C declarations or code"
  13222.     inlineList _ Set new: methods size * 2.
  13223.     methods do: [ :m |
  13224.         inlineIt _ #dontCare.
  13225.         (translationDict includesKey: m selector) ifTrue: [
  13226.             hasCCode _ true.
  13227.         ] ifFalse: [
  13228.             hasCCode _ m declarations size > 0.
  13229.             nodeCount _ 0.
  13230.             m parseTree nodesDo: [ :node |
  13231.                 node isSend ifTrue: [
  13232.                     sel _ node selector.
  13233.                     sel = #cCode: ifTrue: [ hasCCode _ true ].
  13234.                     senderCount _ callsOf at: sel ifAbsent: [ nil ].
  13235.                     nil = senderCount ifFalse: [
  13236.                         callsOf at: sel put: senderCount + 1.
  13237.                     ].
  13238.                 ].
  13239.                 nodeCount _ nodeCount + 1.
  13240.             ].
  13241.             inlineIt _ m extractInlineDirective.  "may be true, false, or #dontCare"
  13242.         ].
  13243.         (hasCCode or: [inlineIt = false]) ifTrue: [
  13244.             "don't inline if method has C code and is contains negative inline directive"
  13245.             methodsNotToInline add: m selector.
  13246.         ] ifFalse: [
  13247.             ((nodeCount < 40) or: [inlineIt = true]) ifTrue: [
  13248.                 "inline if method has no C code and is either small or contains inline directive"
  13249.                 inlineList add: m selector.
  13250.             ].
  13251.         ].
  13252.     ].
  13253.  
  13254.     callsOf associationsDo: [ :assoc |
  13255.         ((assoc value = 1) and: [(methodsNotToInline includes: assoc key) not]) ifTrue: [
  13256.             inlineList add: assoc key.
  13257.         ].
  13258.     ].! !
  13259.  
  13260. !CCodeGenerator methodsFor: 'inlining'!
  13261. doInlining
  13262.     "Inline the bodies of all methods that are suitable for inlining."
  13263.     "Interpreter translate: 'InterpTest.c' doInlining: true"
  13264.  
  13265.     | pass progress |
  13266.     self collectInlineList.
  13267.     "xxx do we need the following?"
  13268.     Interpreter primitiveTable do: [ :sel |
  13269.         inlineList remove: sel ifAbsent: [].
  13270.     ].
  13271.  
  13272.     pass _ 0.
  13273.     progress _ true.
  13274.     [progress] whileTrue: [
  13275.         "repeatedly attempt to inline methods until no further progress is made"
  13276.         progress _ false.
  13277.         ('Inlining pass ', (pass _ pass + 1) printString, '...')
  13278.             displayProgressAt: Sensor cursorPoint
  13279.             from: 0 to: methods size
  13280.             during: [ :bar |
  13281.                 methods doWithIndex: [ :m :i |
  13282.                     bar value: i.
  13283.                     (m tryToInlineMethodsIn: self)
  13284.                         ifTrue: [progress _ true]]].
  13285.     ].
  13286.     'Inlining bytecodes'
  13287.         displayProgressAt: Sensor cursorPoint
  13288.         from: 1 to: 2
  13289.         during: [ :bar |
  13290.             self inlineDispatchesInMethodNamed: #interpret
  13291.                 localizingVars: #(currentBytecode localIP localSP).
  13292.             bar value: 1.
  13293.             self removeMethodsReferingToGlobals: #(currentBytecode localIP localSP)
  13294.                 except: #interpret.
  13295.             bar value: 2.
  13296.     ].
  13297. ! !
  13298.  
  13299. !CCodeGenerator methodsFor: 'inlining' stamp: 'ikp 1/3/98 23:13'!
  13300. doInlining: inlineFlag
  13301.     "Inline the bodies of all methods that are suitable for inlining."
  13302.     "Modified slightly for the translator, since the first level of inlining for the interpret
  13303.     loop must be performed in order that the instruction implementations can easily
  13304.     discover their addresses."
  13305.  
  13306.     "Interpreter translate: 'InterpTest.c' doInlining: true"
  13307.  
  13308.     | pass progress |
  13309.  
  13310.     inlineFlag ifFalse: [
  13311.         ^self inlineDispatchesInMethodNamed: #interpret localizingVars: #().
  13312.     ].
  13313.  
  13314.     self collectInlineList.
  13315.     "xxx do we need the following?"
  13316.     Interpreter primitiveTable do: [ :sel |
  13317.         inlineList remove: sel ifAbsent: [].
  13318.     ].
  13319.  
  13320.     pass _ 0.
  13321.     progress _ true.
  13322.     [progress] whileTrue: [
  13323.         "repeatedly attempt to inline methods until no further progress is made"
  13324.         progress _ false.
  13325.         ('Inlining pass ', (pass _ pass + 1) printString, '...')
  13326.             displayProgressAt: Sensor cursorPoint
  13327.             from: 0 to: methods size
  13328.             during: [ :bar |
  13329.                 methods doWithIndex: [ :m :i |
  13330.                     bar value: i.
  13331.                     (m tryToInlineMethodsIn: self)
  13332.                         ifTrue: [progress _ true]]].
  13333.     ].
  13334.     'Inlining bytecodes'
  13335.         displayProgressAt: Sensor cursorPoint
  13336.         from: 1 to: 3
  13337.         during: [ :bar |
  13338.             self inlineDispatchesInMethodNamed: #interpret
  13339.                 localizingVars: #(currentBytecode localIP localSP localCP localTP).
  13340.             bar value: 1.
  13341. "xxx
  13342.             (methods includesKey: #translateNewMethod) ifTrue:
  13343.                 [self inlineDispatchesInMethodNamed: #translateNewMethod
  13344.                     localizingVars: #(currentByte bytePointer opPointer).
  13345.                 self removeMethodsReferingToGlobals: #(currentByte bytePointer opPointer)
  13346.                     except: #translateNewMethod.
  13347.                 ].
  13348. xxx"
  13349.             bar value: 2.
  13350.             self removeMethodsReferingToGlobals: #(currentBytecode localIP localSP localCP localTP)
  13351.                 except: #interpret.
  13352.             bar value: 3.
  13353.     ].
  13354. ! !
  13355.  
  13356. !CCodeGenerator methodsFor: 'inlining'!
  13357. inlineDispatchesInMethodNamed: selector localizingVars: varsList
  13358.     "Inline dispatches (case statements) in the method with the given name."
  13359.  
  13360.     | m |
  13361.     m _ self methodNamed: selector.
  13362.     m = nil ifFalse: [
  13363.         m inlineCaseStatementBranchesIn: self localizingVars: varsList.
  13364.         m parseTree nodesDo: [ :n |
  13365.             n isCaseStmt ifTrue: [
  13366.                 n customizeShortCasesForDispatchVar: #currentBytecode.
  13367.             ].
  13368.         ].
  13369.     ].
  13370.     variables _ variables asOrderedCollection.
  13371.     varsList do: [ :v |
  13372.         variables remove: v asString ifAbsent: [].
  13373.         (variableDeclarations includesKey: v asString) ifTrue: [
  13374.             m declarations at: v asString put: (variableDeclarations at: v asString).
  13375.             variableDeclarations removeKey: v asString.
  13376.         ].
  13377.     ].
  13378. ! !
  13379.  
  13380. !CCodeGenerator methodsFor: 'inlining'!
  13381. mayInline: sel
  13382.     "Answer true if the method with the given selector may be inlined."
  13383.  
  13384.     ^ inlineList includes: sel! !
  13385.  
  13386. !CCodeGenerator methodsFor: 'inlining'!
  13387. methodStatsString
  13388.     "Return a string describing the size, # of locals, and # of senders of each method. Note methods that have inline C code or C declarations."
  13389.  
  13390.     | methodsWithCCode sizesOf callsOf hasCCode nodeCount senderCount s calls registers selr |
  13391.     methodsWithCCode _ Set new: methods size.
  13392.     sizesOf _ Dictionary new: methods size * 2.  "selector -> nodeCount"
  13393.     callsOf _ Dictionary new: methods size * 2.  "selector -> senderCount"
  13394.  
  13395.     "For each method, scan its parse tree once to:
  13396.         1. determine if the method contains C code or declarations
  13397.         2. determine how many nodes it has
  13398.         3. increment the sender counts of the methods it calls
  13399.         4. determine if it includes any C declarations or code"
  13400.  
  13401.     methods do: [ :m |
  13402.         (translationDict includesKey: m selector) ifTrue: [
  13403.             hasCCode _ true.
  13404.         ] ifFalse: [
  13405.             hasCCode _ m declarations size > 0.
  13406.             nodeCount _ 0.
  13407.             m parseTree nodesDo: [ :node |
  13408.                 node isSend ifTrue: [
  13409.                     selr _ node selector.
  13410.                     selr = #cCode: ifTrue: [ hasCCode _ true ].
  13411.                     senderCount _ callsOf at: selr ifAbsent: [ 0 ].
  13412.                     callsOf at: selr put: senderCount + 1.
  13413.                 ].
  13414.                 nodeCount _ nodeCount + 1.
  13415.             ].
  13416.         ].
  13417.         hasCCode ifTrue: [ methodsWithCCode add: m selector ].
  13418.         sizesOf at: m selector put: nodeCount.
  13419.     ].
  13420.  
  13421.     s _ WriteStream on: (String new: 5000).
  13422.     methods keys asSortedCollection do: [ :sel |
  13423.         m _ methods at: sel.
  13424.         registers _ m locals size + m args size.
  13425.         calls _ callsOf at: sel ifAbsent: [0].
  13426.         registers > 11 ifTrue: [
  13427.             s nextPutAll: sel; tab.
  13428.             s nextPutAll: (sizesOf at: sel) printString; tab.
  13429.             s nextPutAll: calls printString; tab.
  13430.             s nextPutAll: registers printString; tab.
  13431.             (methodsWithCCode includes: sel) ifTrue: [ s nextPutAll: 'CCode' ].
  13432.         s cr.
  13433.         ].
  13434.     ].
  13435.     ^ s contents! !
  13436.  
  13437. !CCodeGenerator methodsFor: 'inlining' stamp: 'ikp 9/26/97 14:50'!
  13438. removeAssertions
  13439.     "Remove all assertions in method bodies.  This is for the benefit of inlining, which
  13440.     fails to recognise and disregard empty method bodies when checking the inlinability
  13441.     of sends."
  13442.  
  13443.     | newMethods |
  13444.     newMethods _ Dictionary new.
  13445.     'Removing assertions...'
  13446.         displayProgressAt: Sensor cursorPoint
  13447.         from: 0 to: methods size
  13448.         during: [ :bar |
  13449.             methods doWithIndex: [ :m :i |
  13450.                 bar value: i.
  13451.                 m isAssertion ifFalse: [
  13452.                     newMethods at: m selector put: m.
  13453.                     m removeAssertions]]].
  13454.     methods _ newMethods.! !
  13455.  
  13456. !CCodeGenerator methodsFor: 'inlining'!
  13457. removeMethodsReferingToGlobals: varList except: methodName
  13458.     "Remove any methods (presumably inlined) that still contain references to the given obsolete global variables."
  13459.  
  13460.     | varListAsStrings removeIt mVars |
  13461.     varListAsStrings _ varList collect: [ :sym | sym asString ].
  13462.     methods keys copy do: [ :sel |
  13463.         removeIt _ false.
  13464.         mVars _ (self methodNamed: sel) freeVariableReferences asSet.
  13465.         varListAsStrings do: [ :v |
  13466.             (mVars includes: v) ifTrue: [ removeIt _ true ].
  13467.         ].
  13468.         (removeIt and: [sel ~= methodName]) ifTrue: [
  13469.             methods removeKey: sel ifAbsent: [].
  13470.         ].
  13471.     ].! !
  13472.  
  13473.  
  13474. !CCodeGenerator methodsFor: 'utilities'!
  13475. addMethod: aTMethod
  13476.     "Add the given method to the code base."
  13477.  
  13478.     (methods includesKey:  aTMethod selector) ifTrue: [
  13479.         self error: 'Method name conflict: ', aTMethod selector.
  13480.     ].
  13481.     methods at: aTMethod selector put: aTMethod.! !
  13482.  
  13483. !CCodeGenerator methodsFor: 'utilities'!
  13484. builtin: sel
  13485.     "Answer true if the given selector is one of the builtin selectors."
  13486.  
  13487.     ((sel = #longAt:) or: [(sel = #longAt:put:) or: [sel = #error:]]) ifTrue: [ ^true ].
  13488.     ((sel = #byteAt:) or: [sel = #byteAt:put:]) ifTrue: [ ^true ].
  13489.     ^translationDict includesKey: sel! !
  13490.  
  13491. !CCodeGenerator methodsFor: 'utilities'!
  13492. cCodeForMethod: selector
  13493.     "Answer a string containing the C code for the given method."
  13494.     "Example:
  13495.         ((CCodeGenerator new initialize addClass: TestCClass1; prepareMethods)
  13496.             cCodeForMethod: #ifTests)"
  13497.  
  13498.     | m s |
  13499.     m _ self methodNamed: selector.
  13500.     m = nil ifTrue: [ self error: 'method not found in code base: ', selector ].
  13501.  
  13502.     s _ (ReadWriteStream on: '').
  13503.     m emitCCodeOn: s generator: self.
  13504.     ^ s contents! !
  13505.  
  13506. !CCodeGenerator methodsFor: 'utilities'!
  13507. emitBuiltinConstructFor: msgNode on: aStream level: level
  13508.     "If the given selector is in the translation dictionary, translate it into a target code construct and return true. Otherwise, do nothing and return false."
  13509.  
  13510.     | action |
  13511.     action _ translationDict at: msgNode selector ifAbsent: [ ^false ].
  13512.     self perform: action with: msgNode with: aStream with: level.
  13513.     ^true! !
  13514.  
  13515. !CCodeGenerator methodsFor: 'utilities'!
  13516. methodNamed: selector
  13517.     "Answer the method in the code base with the given selector."
  13518.  
  13519.     ^ methods at: selector ifAbsent: [ nil ]! !
  13520.  
  13521. !CCodeGenerator methodsFor: 'utilities'!
  13522. methodsReferringToGlobal: v
  13523.     "Return a collection of methods that refer to the given global variable."
  13524.  
  13525.     | out |
  13526.     out _ OrderedCollection new.
  13527.     methods associationsDo: [ :assoc |
  13528.         (assoc value freeVariableReferences includes: v) ifTrue: [
  13529.             out add: assoc key.
  13530.         ].
  13531.     ].
  13532.     ^ out! !
  13533.  
  13534. !CCodeGenerator methodsFor: 'utilities'!
  13535. methodsThatCanInvoke: aSelectorList
  13536.     "Return a set of methods that can invoke one of the given selectors, either directly or via a sequence of intermediate methods."
  13537.  
  13538.     | out todo sel mSelector |
  13539.     out _ Set new.
  13540.     todo _ aSelectorList copy asOrderedCollection.
  13541.     [todo isEmpty] whileFalse: [
  13542.         sel _ todo removeFirst.
  13543.         out add: sel.
  13544.         methods do: [ :m |
  13545.             (m allCalls includes: sel) ifTrue: [
  13546.                 mSelector _ m selector.
  13547.                 ((out includes: mSelector) or:
  13548.                  [todo includes: mSelector]) ifFalse: [
  13549.                     todo add: mSelector.
  13550.                 ].
  13551.             ].
  13552.         ].
  13553.     ].
  13554.     ^ out
  13555.     ! !
  13556.  
  13557. !CCodeGenerator methodsFor: 'utilities'!
  13558. prepareMethods
  13559.     "Prepare methods for browsing."
  13560.  
  13561.     | globals |
  13562.     globals _ Set new: 200.
  13563.     globals addAll: variables.
  13564.     methods do: [ :m |
  13565.         (m locals, m args) do: [ :var |
  13566.             (globals includes: var) ifTrue: [
  13567.                 self error: 'Local variable name may mask global when inlining: ', var.
  13568.             ].
  13569.             (methods includesKey: var) ifTrue: [
  13570.                 self error: 'Local variable name may mask method when inlining: ', var.
  13571.             ].    
  13572.         ].
  13573.         m bindClassVariablesIn: constants.
  13574.         m prepareMethodIn: self.
  13575.     ].! !
  13576.  
  13577. !CCodeGenerator methodsFor: 'utilities'!
  13578. reportRecursiveMethods
  13579.     "Report in transcript all methods that can call themselves directly or indirectly or via a chain of N intermediate methods."
  13580.  
  13581.     | visited calls newCalls sel called |
  13582.     methods do: [: m |
  13583.         visited _ translationDict keys asSet.
  13584.         calls _ m allCalls asOrderedCollection.
  13585.         5 timesRepeat: [
  13586.             newCalls _ Set new: 50.
  13587.             [calls isEmpty] whileFalse: [
  13588.                 sel _ calls removeFirst.
  13589.                 sel = m selector ifTrue: [
  13590.                     Transcript show: m selector, ' is recursive'; cr.
  13591.                 ] ifFalse: [
  13592.                     (visited includes: sel) ifFalse: [
  13593.                         called _ self methodNamed: sel.
  13594.                         called = nil ifFalse: [ newCalls addAll: called allCalls ].
  13595.                     ].
  13596.                     visited add: sel.
  13597.                 ].
  13598.             ].
  13599.             calls _ newCalls asOrderedCollection.
  13600.         ].
  13601.     ].! !
  13602.  
  13603. !CCodeGenerator methodsFor: 'utilities'!
  13604. unreachableMethods
  13605.     "Return a collection of methods that are never invoked."
  13606.  
  13607.     | sent out |
  13608.     sent _ Set new.
  13609.     methods do: [ :m |
  13610.         sent addAll: m allCalls.
  13611.     ].
  13612.  
  13613.     out _ OrderedCollection new.
  13614.     methods keys do: [ :sel |
  13615.         (sent includes: sel) ifFalse: [ out add: sel ].
  13616.     ].
  13617.     ^ out! !
  13618.  
  13619.  
  13620. !CCodeGenerator methodsFor: 'C code generator'!
  13621. cFunctionNameFor: aSelector
  13622.     "Create a C function name from the given selector by omitting colons."
  13623.  
  13624.     ^aSelector copyWithout: $:! !
  13625.  
  13626. !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 12/2/97 19:40'!
  13627. cLiteralFor: anObject
  13628.     "Return a string representing the C literal value for the given object."
  13629.     | s |
  13630.     (anObject isKindOf: Integer) ifTrue: [
  13631.         (anObject < 16r7FFFFFFF)
  13632.             ifTrue: [^ anObject printString]
  13633.             ifFalse: [^ anObject printString , 'U']].
  13634.     (anObject isKindOf: String) ifTrue: [^ '"', anObject, '"' ].
  13635.     (anObject isKindOf: Float) ifTrue: [^ anObject printString ].
  13636.     anObject == nil ifTrue: [^ 'null' ].
  13637.     anObject == true ifTrue: [^ '1' ].            "ikp"
  13638.     anObject == false ifTrue: [^ '0' ].            "ikp"
  13639.     self error:                                "ikp"
  13640.         'Warning: A Smalltalk literal could not be translated into a C constant: ', anObject printString.
  13641.     ^'"XXX UNTRANSLATABLE CONSTANT XXX"'! !
  13642.  
  13643. !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 12/7/97 20:54'!
  13644. emitCCodeOn: aStream doInlining: inlineFlag
  13645.  
  13646.     self emitCCodeOn: aStream doInlining: inlineFlag doAssertions: true! !
  13647.  
  13648. !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 12/7/97 20:54'!
  13649. emitCCodeOn: aStream doInlining: inlineFlag doAssertions: assertionFlag
  13650.     "Emit C code for all methods in the code base onto the given stream. All inlined method calls should already have been expanded."
  13651.  
  13652.     | verbose |
  13653.     "method preparation"
  13654.     verbose _ false.
  13655.     self prepareMethods.
  13656.     verbose ifTrue: [
  13657.         self printUnboundCallWarnings.
  13658.         self printUnboundVariableReferenceWarnings.
  13659.         Transcript cr.
  13660.     ].
  13661.     assertionFlag ifFalse: [ self removeAssertions ].
  13662.     self doInlining: inlineFlag.
  13663.  
  13664.     "code generation"
  13665.     methods _ methods asSortedCollection: [ :m1 :m2 | m1 selector < m2 selector ].
  13666.     self emitCHeaderOn: aStream.
  13667.     self emitCVariablesOn: aStream.
  13668.     self emitCFunctionPrototypesOn: aStream.
  13669. 'Writing Translated Code...'
  13670. displayProgressAt: Sensor cursorPoint
  13671. from: 0 to: methods size
  13672. during: [:bar |
  13673.     methods doWithIndex: [ :m :i | bar value: i.
  13674.         m emitCCodeOn: aStream generator: self.
  13675. ]].! !
  13676.  
  13677. !CCodeGenerator methodsFor: 'C code generator'!
  13678. emitCExpression: aParseNode on: aStream
  13679.     "Emit C code for the expression described by the given parse node."
  13680.  
  13681.     aParseNode isLeaf ifTrue: [
  13682.         "omit parens"
  13683.         aParseNode emitCCodeOn: aStream level: 0 generator: self.
  13684.     ] ifFalse: [
  13685.         aStream nextPut: $(.
  13686.         aParseNode emitCCodeOn: aStream level: 0 generator: self.
  13687.         aStream nextPut: $).
  13688.     ].! !
  13689.  
  13690. !CCodeGenerator methodsFor: 'C code generator'!
  13691. emitCFunctionPrototypesOn: aStream
  13692.     "Store prototype declarations for all non-inlined methods on the given stream."
  13693.  
  13694.     aStream nextPutAll: '/*** Function Prototypes ***/'; cr.
  13695.     methods do: [ :m |
  13696.         m emitCFunctionPrototype: aStream generator: self.
  13697.         aStream nextPutAll: ';'; cr.
  13698.     ].! !
  13699.  
  13700. !CCodeGenerator methodsFor: 'C code generator' stamp: 'ikp 1/4/98 00:03'!
  13701. emitCHeaderForPrimitivesOn: aStream
  13702.     "Write a C file header for compiled primitives onto the given stream."
  13703.  
  13704.     aStream nextPutAll: '/* Automatically generated from Squeak on '.
  13705.     aStream nextPutAll: Time dateAndTimeNow printString.
  13706.     aStream nextPutAll: ' */'; cr; cr.
  13707.  
  13708.     aStream nextPutAll: '#include "sq.h"'; cr; cr.
  13709.  
  13710.     aStream nextPutAll: '
  13711. /* Memory Access Macros */
  13712. #define byteAt(i) (*((unsigned char *) (i)))
  13713. #define byteAtput(i, val) (*((unsigned char *) (i)) = val)
  13714. #define longAt(i) (*((int *) (i)))
  13715. #define longAtput(i, val) (*((int *) (i)) = val)
  13716.  
  13717. /*** Imported Functions/Variables ***/
  13718. extern int stackValue(int);
  13719. extern int successFlag;
  13720. '.
  13721.     aStream cr.! !
  13722.  
  13723. !CCodeGenerator methodsFor: 'C code generator' stamp: 'jm 2/1/98 15:35'!
  13724. emitCHeaderOn: aStream
  13725.     "Write a C file header onto the given stream."
  13726.  
  13727.     aStream nextPutAll: '/* Automatically generated from Squeak on '.
  13728.     aStream nextPutAll: Time dateAndTimeNow printString.
  13729.     aStream nextPutAll: ' */'; cr; cr.
  13730.  
  13731.     aStream nextPutAll: '#include "sq.h"'; cr.
  13732.     aStream nextPutAll: '#include "sqMachDep.h"  /* needed only by the JIT virtual machine */'; cr.
  13733.  
  13734.     aStream nextPutAll: '
  13735. /* memory access macros */
  13736. #define byteAt(i) (*((unsigned char *) (i)))
  13737. #define byteAtput(i, val) (*((unsigned char *) (i)) = val)
  13738. #define longAt(i) (*((int *) (i)))
  13739. #define longAtput(i, val) (*((int *) (i)) = val)
  13740.  
  13741. int printCallStack(void);
  13742. void error(char *s);
  13743. void error(char *s) {
  13744.     /* Print an error message and exit. */
  13745.     static int printingStack = false;
  13746.  
  13747.     printf("\n%s\n\n", s);
  13748.     if (!!printingStack) {
  13749.         /* flag prevents recursive error when trying to print a broken stack */
  13750.         printingStack = true;
  13751.         printCallStack();
  13752.     }
  13753.     exit(-1);
  13754. }
  13755. '.
  13756.     aStream cr.! !
  13757.  
  13758. !CCodeGenerator methodsFor: 'C code generator'!
  13759. emitCTestBlock: aBlockNode on: aStream
  13760.     "Emit C code for the given block node to be used as a loop test."
  13761.  
  13762.     aBlockNode statements size > 1 ifTrue: [
  13763.         aBlockNode emitCCodeOn: aStream level: 0 generator: self.
  13764.     ] ifFalse: [
  13765.         aBlockNode statements first emitCCodeOn: aStream level: 0 generator: self.
  13766.     ].! !
  13767.  
  13768. !CCodeGenerator methodsFor: 'C code generator'!
  13769. emitCVariablesOn: aStream
  13770.     "Store the global variable declarations on the given stream."
  13771.  
  13772.     aStream nextPutAll: '/*** Variables ***/'; cr.
  13773.     variables asSortedCollection do: [ :var |
  13774.         (variableDeclarations includesKey: var) ifTrue: [
  13775.             aStream nextPutAll: (variableDeclarations at: var), ';'; cr.
  13776.         ] ifFalse: [
  13777.             "default variable declaration"
  13778.             aStream nextPutAll: 'int ', var, ';'; cr.
  13779.         ].
  13780.     ].
  13781.     aStream cr.! !
  13782.  
  13783.  
  13784. !CCodeGenerator methodsFor: 'C translation'!
  13785. generateAnd: msgNode on: aStream indent: level
  13786.     "Generate the C code for this message onto the given stream."
  13787.  
  13788.     self emitCExpression: msgNode receiver on: aStream.
  13789.     aStream nextPutAll: ' && '.
  13790.     self emitCExpression: msgNode args first on: aStream.! !
  13791.  
  13792. !CCodeGenerator methodsFor: 'C translation'!
  13793. generateAt: msgNode on: aStream indent: level
  13794.     "Generate the C code for this message onto the given stream."
  13795.  
  13796.     self emitCExpression: msgNode receiver on: aStream.
  13797.     aStream nextPutAll: '['.
  13798.     msgNode args first emitCCodeOn: aStream level: level generator: self.
  13799.     aStream nextPutAll: ']'.! !
  13800.  
  13801. !CCodeGenerator methodsFor: 'C translation'!
  13802. generateAtPut: msgNode on: aStream indent: level
  13803.     "Generate the C code for this message onto the given stream."
  13804.  
  13805.     self emitCExpression: msgNode receiver on: aStream.
  13806.     aStream nextPutAll: '['.
  13807.     msgNode args first emitCCodeOn: aStream level: level generator: self.
  13808.     aStream nextPutAll: '] = '.
  13809.     self emitCExpression: msgNode args last on: aStream.! !
  13810.  
  13811. !CCodeGenerator methodsFor: 'C translation'!
  13812. generateBitAnd: msgNode on: aStream indent: level
  13813.     "Generate the C code for this message onto the given stream."
  13814.  
  13815.     self emitCExpression: msgNode receiver on: aStream.
  13816.     aStream nextPutAll: ' & '.
  13817.     self emitCExpression: msgNode args first on: aStream.! !
  13818.  
  13819. !CCodeGenerator methodsFor: 'C translation'!
  13820. generateBitInvert32: msgNode on: aStream indent: level
  13821.     "Generate the C code for this message onto the given stream."
  13822.  
  13823.     aStream nextPutAll: '~'.
  13824.     self emitCExpression: msgNode receiver on: aStream.! !
  13825.  
  13826. !CCodeGenerator methodsFor: 'C translation'!
  13827. generateBitOr: msgNode on: aStream indent: level
  13828.     "Generate the C code for this message onto the given stream."
  13829.  
  13830.     self emitCExpression: msgNode receiver on: aStream.
  13831.     aStream nextPutAll: ' | '.
  13832.     self emitCExpression: msgNode args first on: aStream.! !
  13833.  
  13834. !CCodeGenerator methodsFor: 'C translation'!
  13835. generateBitShift: msgNode on: aStream indent: level
  13836.     "Generate the C code for this message onto the given stream."
  13837.  
  13838.     | arg rcvr |
  13839.     arg _ msgNode args first.
  13840.     rcvr _ msgNode receiver.
  13841.     arg isConstant ifTrue: [
  13842.         "bit shift amount is a constant"
  13843.         aStream nextPutAll: '((unsigned) '.
  13844.         self emitCExpression: rcvr on: aStream.
  13845.         arg value < 0 ifTrue: [
  13846.             aStream nextPutAll: ' >> ', arg value negated printString.
  13847.         ] ifFalse: [
  13848.             aStream nextPutAll: ' << ', arg value printString.
  13849.         ].
  13850.         aStream nextPutAll: ')'.
  13851.     ] ifFalse: [
  13852.         "bit shift amount is an expression"
  13853.         aStream nextPutAll: '(('.
  13854.         self emitCExpression: arg on: aStream.
  13855.         aStream nextPutAll: ' < 0) ? ((unsigned) '.
  13856.         self emitCExpression: rcvr on: aStream.
  13857.         aStream nextPutAll: ' >> -'.
  13858.         self emitCExpression: arg on: aStream.
  13859.         aStream nextPutAll: ') : ((unsigned) '.
  13860.         self emitCExpression: rcvr on: aStream.
  13861.         aStream nextPutAll: ' << '.
  13862.         self emitCExpression: arg on: aStream.
  13863.         aStream nextPutAll: '))'.
  13864.     ].! !
  13865.  
  13866. !CCodeGenerator methodsFor: 'C translation'!
  13867. generateBitXor: msgNode on: aStream indent: level
  13868.     "Generate the C code for this message onto the given stream."
  13869.  
  13870.     self emitCExpression: msgNode receiver on: aStream.
  13871.     aStream nextPutAll: ' ^ '.
  13872.     self emitCExpression: msgNode args first on: aStream.! !
  13873.  
  13874. !CCodeGenerator methodsFor: 'C translation'!
  13875. generateCCoercion: msgNode on: aStream indent: level
  13876.     "Generate the C code for this message onto the given stream."
  13877.  
  13878.     aStream nextPutAll: '(('.
  13879.     aStream nextPutAll: msgNode args last value.
  13880.     aStream nextPutAll: ') '.
  13881.     self emitCExpression: msgNode args first on: aStream.
  13882.     aStream nextPutAll: ')'.
  13883.  
  13884. ! !
  13885.  
  13886. !CCodeGenerator methodsFor: 'C translation'!
  13887. generateDivide: msgNode on: aStream indent: level
  13888.     "Generate the C code for this message onto the given stream."
  13889.  
  13890.     self emitCExpression: msgNode receiver on: aStream.
  13891.     aStream nextPutAll: ' / '.
  13892.     self emitCExpression: msgNode args first on: aStream.! !
  13893.  
  13894. !CCodeGenerator methodsFor: 'C translation'!
  13895. generateEqual: msgNode on: aStream indent: level
  13896.     "Generate the C code for this message onto the given stream."
  13897.  
  13898.     self emitCExpression: msgNode receiver on: aStream.
  13899.     aStream nextPutAll: ' == '.
  13900.     self emitCExpression: msgNode args first on: aStream.! !
  13901.  
  13902. !CCodeGenerator methodsFor: 'C translation'!
  13903. generateGreaterThan: msgNode on: aStream indent: level
  13904.     "Generate the C code for this message onto the given stream."
  13905.  
  13906.     self emitCExpression: msgNode receiver on: aStream.
  13907.     aStream nextPutAll: ' > '.
  13908.     self emitCExpression: msgNode args first on: aStream.! !
  13909.  
  13910. !CCodeGenerator methodsFor: 'C translation'!
  13911. generateGreaterThanOrEqual: msgNode on: aStream indent: level
  13912.     "Generate the C code for this message onto the given stream."
  13913.  
  13914.     self emitCExpression: msgNode receiver on: aStream.
  13915.     aStream nextPutAll: ' >= '.
  13916.     self emitCExpression: msgNode args first on: aStream.! !
  13917.  
  13918. !CCodeGenerator methodsFor: 'C translation'!
  13919. generateIfFalse: msgNode on: aStream indent: level
  13920.     "Generate the C code for this message onto the given stream."
  13921.     "Note: PP 2.3 compiler produces two arguments for ifFalse:, presumably
  13922.      to help with inlining later. Taking the last agument should do the correct
  13923.      thing even if your compiler is different."
  13924.  
  13925.     aStream nextPutAll: 'if (!!('.
  13926.     msgNode receiver emitCCodeOn: aStream level: level generator: self.
  13927.     aStream nextPutAll: ')) {'; cr.
  13928.     msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  13929.     level timesRepeat: [ aStream tab ].
  13930.     aStream nextPutAll: '}'.! !
  13931.  
  13932. !CCodeGenerator methodsFor: 'C translation'!
  13933. generateIfFalseIfTrue: msgNode on: aStream indent: level
  13934.     "Generate the C code for this message onto the given stream."
  13935.     "Note: PP 2.3 compiler reverses the argument blocks for ifFalse:ifTrue:,
  13936.        presumably to help with inlining later. That is, the first argument
  13937.        is the block to be evaluated if the condition is true."
  13938.  
  13939.     aStream nextPutAll: 'if ('.
  13940.     msgNode receiver emitCCodeOn: aStream level: level generator: self.
  13941.     aStream nextPutAll: ') {'; cr.
  13942.     msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  13943.     level timesRepeat: [ aStream tab ].
  13944.     aStream nextPutAll: '} else {'; cr.
  13945.     msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  13946.     level timesRepeat: [ aStream tab ].
  13947.     aStream nextPutAll: '}'.! !
  13948.  
  13949. !CCodeGenerator methodsFor: 'C translation'!
  13950. generateIfTrue: msgNode on: aStream indent: level
  13951.     "Generate the C code for this message onto the given stream."
  13952.  
  13953.     aStream nextPutAll: 'if ('.
  13954.     msgNode receiver emitCCodeOn: aStream level: level generator: self.
  13955.     aStream nextPutAll: ') {'; cr.
  13956.     msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  13957.     level timesRepeat: [ aStream tab ].
  13958.     aStream nextPutAll: '}'.! !
  13959.  
  13960. !CCodeGenerator methodsFor: 'C translation'!
  13961. generateIfTrueIfFalse: msgNode on: aStream indent: level
  13962.     "Generate the C code for this message onto the given stream."
  13963.  
  13964.     aStream nextPutAll: 'if ('.
  13965.     msgNode receiver emitCCodeOn: aStream level: level generator: self.
  13966.     aStream nextPutAll: ') {'; cr.
  13967.     msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  13968.     level timesRepeat: [ aStream tab ].
  13969.     aStream nextPutAll: '} else {'; cr.
  13970.     msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  13971.     level timesRepeat: [ aStream tab ].
  13972.     aStream nextPutAll: '}'.! !
  13973.  
  13974. !CCodeGenerator methodsFor: 'C translation'!
  13975. generateInlineCCode: msgNode on: aStream indent: level
  13976.     "Generate the C code for this message onto the given stream."
  13977.  
  13978.     aStream nextPutAll: msgNode args first value.! !
  13979.  
  13980. !CCodeGenerator methodsFor: 'C translation'!
  13981. generateInlineDirective: msgNode on: aStream indent: level
  13982.     "Generate the C code for this message onto the given stream."
  13983.  
  13984.     aStream nextPutAll: '/* inline: '.
  13985.     aStream nextPutAll: msgNode args first name.
  13986.     aStream nextPutAll: ' */'.
  13987. ! !
  13988.  
  13989. !CCodeGenerator methodsFor: 'C translation'!
  13990. generateIntegerObjectOf: msgNode on: aStream indent: level
  13991.     "Generate the C code for this message onto the given stream."
  13992.  
  13993.     aStream nextPutAll: '(('.
  13994.     self emitCExpression: msgNode args first on: aStream.
  13995.     aStream nextPutAll: ' << 1) | 1)'.! !
  13996.  
  13997. !CCodeGenerator methodsFor: 'C translation'!
  13998. generateIntegerValueOf: msgNode on: aStream indent: level
  13999.     "Generate the C code for this message onto the given stream."
  14000.  
  14001.     aStream nextPutAll: '('.
  14002.     self emitCExpression: msgNode args first on: aStream.
  14003.     aStream nextPutAll: ' >> 1)'.! !
  14004.  
  14005. !CCodeGenerator methodsFor: 'C translation'!
  14006. generateIsIntegerObject: msgNode on: aStream indent: level
  14007.     "Generate the C code for this message onto the given stream."
  14008.  
  14009.     aStream nextPutAll: '('.
  14010.     self emitCExpression: msgNode args first on: aStream.
  14011.     aStream nextPutAll: ' & 1)'.! !
  14012.  
  14013. !CCodeGenerator methodsFor: 'C translation'!
  14014. generateIsNil: msgNode on: aStream indent: level
  14015.     "Generate the C code for this message onto the given stream."
  14016.  
  14017.     self emitCExpression: msgNode receiver on: aStream.
  14018.     aStream nextPutAll: ' == '.
  14019.     aStream nextPutAll: (self cLiteralFor: nil).! !
  14020.  
  14021. !CCodeGenerator methodsFor: 'C translation'!
  14022. generateLessThan: msgNode on: aStream indent: level
  14023.     "Generate the C code for this message onto the given stream."
  14024.  
  14025.     self emitCExpression: msgNode receiver on: aStream.
  14026.     aStream nextPutAll: ' < '.
  14027.     self emitCExpression: msgNode args first on: aStream.! !
  14028.  
  14029. !CCodeGenerator methodsFor: 'C translation'!
  14030. generateLessThanOrEqual: msgNode on: aStream indent: level
  14031.     "Generate the C code for this message onto the given stream."
  14032.  
  14033.     self emitCExpression: msgNode receiver on: aStream.
  14034.     aStream nextPutAll: ' <= '.
  14035.     self emitCExpression: msgNode args first on: aStream.! !
  14036.  
  14037. !CCodeGenerator methodsFor: 'C translation'!
  14038. generateMax: msgNode on: aStream indent: level
  14039.     "Generate the C code for this message onto the given stream."
  14040.  
  14041.     aStream nextPutAll: '(('.
  14042.     self emitCExpression: msgNode receiver on: aStream.
  14043.     aStream nextPutAll: ' < '.
  14044.     self emitCExpression: msgNode args first on: aStream.
  14045.     aStream nextPutAll: ') ? '.
  14046.     self emitCExpression: msgNode args first on: aStream.
  14047.     aStream nextPutAll: ' : '.
  14048.     self emitCExpression: msgNode receiver on: aStream.
  14049.     aStream nextPutAll: ')'.! !
  14050.  
  14051. !CCodeGenerator methodsFor: 'C translation'!
  14052. generateMin: msgNode on: aStream indent: level
  14053.     "Generate the C code for this message onto the given stream."
  14054.  
  14055.     aStream nextPutAll: '(('.
  14056.     self emitCExpression: msgNode receiver on: aStream.
  14057.     aStream nextPutAll: ' < '.
  14058.     self emitCExpression: msgNode args first on: aStream.
  14059.     aStream nextPutAll: ') ? '.
  14060.     self emitCExpression: msgNode receiver on: aStream.
  14061.     aStream nextPutAll: ' : '.
  14062.     self emitCExpression: msgNode args first on: aStream.
  14063.     aStream nextPutAll: ')'.! !
  14064.  
  14065. !CCodeGenerator methodsFor: 'C translation'!
  14066. generateMinus: msgNode on: aStream indent: level
  14067.     "Generate the C code for this message onto the given stream."
  14068.  
  14069.     self emitCExpression: msgNode receiver on: aStream.
  14070.     aStream nextPutAll: ' - '.
  14071.     self emitCExpression: msgNode args first on: aStream.! !
  14072.  
  14073. !CCodeGenerator methodsFor: 'C translation'!
  14074. generateModulo: msgNode on: aStream indent: level
  14075.     "Generate the C code for this message onto the given stream."
  14076.  
  14077.     self emitCExpression: msgNode receiver on: aStream.
  14078.     aStream nextPutAll: ' % '.
  14079.     self emitCExpression: msgNode args first on: aStream.! !
  14080.  
  14081. !CCodeGenerator methodsFor: 'C translation'!
  14082. generateNot: msgNode on: aStream indent: level
  14083.     "Generate the C code for this message onto the given stream."
  14084.  
  14085.     aStream nextPutAll: '!!'.
  14086.     self emitCExpression: msgNode receiver on: aStream.! !
  14087.  
  14088. !CCodeGenerator methodsFor: 'C translation'!
  14089. generateNotEqual: msgNode on: aStream indent: level
  14090.     "Generate the C code for this message onto the given stream."
  14091.  
  14092.     self emitCExpression: msgNode receiver on: aStream.
  14093.     aStream nextPutAll: ' !!= '.
  14094.     self emitCExpression: msgNode args first on: aStream.! !
  14095.  
  14096. !CCodeGenerator methodsFor: 'C translation'!
  14097. generateNotNil: msgNode on: aStream indent: level
  14098.     "Generate the C code for this message onto the given stream."
  14099.  
  14100.     self emitCExpression: msgNode receiver on: aStream.
  14101.     aStream nextPutAll: ' !!= '.
  14102.     aStream nextPutAll: (self cLiteralFor: nil).! !
  14103.  
  14104. !CCodeGenerator methodsFor: 'C translation'!
  14105. generateOr: msgNode on: aStream indent: level
  14106.     "Generate the C code for this message onto the given stream."
  14107.  
  14108.     self emitCExpression: msgNode receiver on: aStream.
  14109.     aStream nextPutAll: ' || '.
  14110.     self emitCExpression: msgNode args first on: aStream.! !
  14111.  
  14112. !CCodeGenerator methodsFor: 'C translation'!
  14113. generatePlus: msgNode on: aStream indent: level
  14114.     "Generate the C code for this message onto the given stream."
  14115.  
  14116.     self emitCExpression: msgNode receiver on: aStream.
  14117.     aStream nextPutAll: ' + '.
  14118.     self emitCExpression: msgNode args first on: aStream.! !
  14119.  
  14120. !CCodeGenerator methodsFor: 'C translation'!
  14121. generatePreDecrement: msgNode on: aStream indent: level
  14122.     "Generate the C code for this message onto the given stream."
  14123.  
  14124.     | varNode |
  14125.     varNode _ msgNode receiver.
  14126.     varNode isVariable
  14127.         ifFalse: [ self error: 'preDecrement can only be applied to variables' ].
  14128.     aStream nextPutAll: '--'.
  14129.     aStream nextPutAll: varNode name.
  14130. ! !
  14131.  
  14132. !CCodeGenerator methodsFor: 'C translation'!
  14133. generatePreIncrement: msgNode on: aStream indent: level
  14134.     "Generate the C code for this message onto the given stream."
  14135.  
  14136.     | varNode |
  14137.     varNode _ msgNode receiver.
  14138.     varNode isVariable
  14139.         ifFalse: [ self error: 'preIncrement can only be applied to variables' ].
  14140.     aStream nextPutAll: '++'.
  14141.     aStream nextPutAll: varNode name.
  14142. ! !
  14143.  
  14144. !CCodeGenerator methodsFor: 'C translation'!
  14145. generateSequentialAnd: msgNode on: aStream indent: level
  14146.     "Generate the C code for this message onto the given stream."
  14147.  
  14148.     self emitCExpression: msgNode receiver on: aStream.
  14149.     aStream nextPutAll: ' && ('.
  14150.     self emitCTestBlock: msgNode args first on: aStream.
  14151.     aStream nextPutAll: ')'.! !
  14152.  
  14153. !CCodeGenerator methodsFor: 'C translation'!
  14154. generateSequentialOr: msgNode on: aStream indent: level
  14155.     "Generate the C code for this message onto the given stream."
  14156.     "Note: PP 2.3 compiler produces two arguments for or:, presumably
  14157.      to help with inlining later. Taking the last agument should do the correct
  14158.      thing even if your compiler is different."
  14159.  
  14160.     self emitCExpression: msgNode receiver on: aStream.
  14161.     aStream nextPutAll: ' || ('.
  14162.     self emitCTestBlock: msgNode args last on: aStream.
  14163.     aStream nextPutAll: ')'.! !
  14164.  
  14165. !CCodeGenerator methodsFor: 'C translation'!
  14166. generateSharedCodeDirective: msgNode on: aStream indent: level
  14167.     "Generate the C code for this message onto the given stream."
  14168.  
  14169.     aStream nextPutAll: '/* common code: '.
  14170.     aStream nextPutAll: msgNode args first value.
  14171.     aStream nextPutAll: ' */'.
  14172. ! !
  14173.  
  14174. !CCodeGenerator methodsFor: 'C translation'!
  14175. generateShiftLeft: msgNode on: aStream indent: level
  14176.     "Generate the C code for this message onto the given stream."
  14177.  
  14178.     self emitCExpression: msgNode receiver on: aStream.
  14179.     aStream nextPutAll: ' << '.
  14180.     self emitCExpression: msgNode args first on: aStream.! !
  14181.  
  14182. !CCodeGenerator methodsFor: 'C translation'!
  14183. generateShiftRight: msgNode on: aStream indent: level
  14184.     "Generate the C code for this message onto the given stream."
  14185.  
  14186.     aStream nextPutAll: '((unsigned) '.
  14187.     self emitCExpression: msgNode receiver on: aStream.
  14188.     aStream nextPutAll: ')'.
  14189.     aStream nextPutAll: ' >> '.
  14190.     self emitCExpression: msgNode args first on: aStream.! !
  14191.  
  14192. !CCodeGenerator methodsFor: 'C translation'!
  14193. generateTimes: msgNode on: aStream indent: level
  14194.     "Generate the C code for this message onto the given stream."
  14195.  
  14196.     self emitCExpression: msgNode receiver on: aStream.
  14197.     aStream nextPutAll: ' * '.
  14198.     self emitCExpression: msgNode args first on: aStream.! !
  14199.  
  14200. !CCodeGenerator methodsFor: 'C translation'!
  14201. generateToByDo: msgNode on: aStream indent: level
  14202.     "Generate the C code for this message onto the given stream."
  14203.  
  14204.     | iterationVar |
  14205.     (msgNode args last args size = 1) ifFalse: [
  14206.         self error: 'wrong number of block arguments'.
  14207.     ].
  14208.     iterationVar _ msgNode args last args first.
  14209.     aStream nextPutAll: 'for (', iterationVar, ' = '.
  14210.     self emitCExpression: msgNode receiver on: aStream.
  14211.     aStream nextPutAll: '; ', iterationVar, ' <= '.
  14212.     self emitCExpression: msgNode args first on: aStream.
  14213.     aStream nextPutAll: '; ', iterationVar, ' += '.
  14214.     self emitCExpression: (msgNode args at: 2) on: aStream.
  14215.     aStream nextPutAll: ') {'; cr.
  14216.     msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  14217.     level timesRepeat: [ aStream tab ].
  14218.     aStream nextPutAll: '}'.! !
  14219.  
  14220. !CCodeGenerator methodsFor: 'C translation'!
  14221. generateToDo: msgNode on: aStream indent: level
  14222.     "Generate the C code for this message onto the given stream."
  14223.  
  14224.     | iterationVar |
  14225.     (msgNode args last args size = 1) ifFalse: [
  14226.         self error: 'wrong number of block arguments'.
  14227.     ].
  14228.     iterationVar _ msgNode args last args first.
  14229.     aStream nextPutAll: 'for (', iterationVar, ' = '.
  14230.     self emitCExpression: msgNode receiver on: aStream.
  14231.     aStream nextPutAll: '; ', iterationVar, ' <= '.
  14232.     self emitCExpression: msgNode args first on: aStream.
  14233.     aStream nextPutAll: '; ', iterationVar, '++) {'; cr.
  14234.     msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  14235.     level timesRepeat: [ aStream tab ].
  14236.     aStream nextPutAll: '}'.! !
  14237.  
  14238. !CCodeGenerator methodsFor: 'C translation'!
  14239. generateWhileFalse: msgNode on: aStream indent: level
  14240.     "Generate the C code for this message onto the given stream."
  14241.  
  14242.     aStream nextPutAll: 'while (!!('.
  14243.     self emitCTestBlock: msgNode receiver on: aStream.
  14244.     aStream nextPutAll: ')) {'; cr.
  14245.     msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  14246.     level timesRepeat: [ aStream tab ].
  14247.     aStream nextPutAll: '}'.! !
  14248.  
  14249. !CCodeGenerator methodsFor: 'C translation'!
  14250. generateWhileTrue: msgNode on: aStream indent: level
  14251.     "Generate the C code for this message onto the given stream."
  14252.  
  14253.     aStream nextPutAll: 'while ('.
  14254.     self emitCTestBlock: msgNode receiver on: aStream.
  14255.     aStream nextPutAll: ') {'; cr.
  14256.     msgNode args first emitCCodeOn: aStream level: level + 1 generator: self.
  14257.     level timesRepeat: [ aStream tab ].
  14258.     aStream nextPutAll: '}'.! !
  14259.  
  14260. !CCodeGenerator methodsFor: 'C translation' stamp: 'jm 2/15/98 17:07'!
  14261. initializeCTranslationDictionary 
  14262.     "Initialize the dictionary mapping message names to actions for C code generation."
  14263.  
  14264.     | pairs |
  14265.     translationDict _ Dictionary new: 200.
  14266.     pairs _ #(
  14267.     #&                #generateAnd:on:indent:
  14268.     #|                #generateOr:on:indent:
  14269.     #and:            #generateSequentialAnd:on:indent:
  14270.     #or:            #generateSequentialOr:on:indent:
  14271.     #not            #generateNot:on:indent:
  14272.  
  14273.     #+                #generatePlus:on:indent:
  14274.     #-                #generateMinus:on:indent:
  14275.     #*                #generateTimes:on:indent:
  14276.     #//                #generateDivide:on:indent:
  14277.     #\\                #generateModulo:on:indent:
  14278.     #<<                #generateShiftLeft:on:indent:
  14279.     #>>                #generateShiftRight:on:indent:
  14280.     #min:            #generateMin:on:indent:
  14281.     #max:            #generateMax:on:indent:
  14282.  
  14283.     #bitAnd:        #generateBitAnd:on:indent:
  14284.     #bitOr:            #generateBitOr:on:indent:
  14285.     #bitXor:            #generateBitXor:on:indent:
  14286.     #bitShift:        #generateBitShift:on:indent:
  14287.     #bitInvert32    #generateBitInvert32:on:indent:
  14288.  
  14289.     #<                #generateLessThan:on:indent:
  14290.     #<=                #generateLessThanOrEqual:on:indent:
  14291.     #=                #generateEqual:on:indent:
  14292.     #>                #generateGreaterThan:on:indent:
  14293.     #>=                #generateGreaterThanOrEqual:on:indent:
  14294.     #~=                #generateNotEqual:on:indent:
  14295.     #==                #generateEqual:on:indent:
  14296.     #isNil            #generateIsNil:on:indent:
  14297.     #notNil            #generateNotNil:on:indent:
  14298.  
  14299.     #whileTrue:     #generateWhileTrue:on:indent:
  14300.     #whileFalse:    #generateWhileFalse:on:indent:
  14301.     #to:do:            #generateToDo:on:indent:
  14302.     #to:by:do:        #generateToByDo:on:indent:
  14303.  
  14304.     #ifTrue:        #generateIfTrue:on:indent:
  14305.     #ifFalse:        #generateIfFalse:on:indent:
  14306.     #ifTrue:ifFalse:    #generateIfTrueIfFalse:on:indent:
  14307.     #ifFalse:ifTrue:    #generateIfFalseIfTrue:on:indent:
  14308.  
  14309.     #at:                #generateAt:on:indent:
  14310.     #at:put:            #generateAtPut:on:indent:
  14311.     #basicAt:        #generateAt:on:indent:
  14312.     #basicAt:put:    #generateAtPut:on:indent:
  14313.  
  14314.     #integerValueOf:    #generateIntegerValueOf:on:indent:
  14315.     #integerObjectOf:    #generateIntegerObjectOf:on:indent:
  14316.     #isIntegerObject:     #generateIsIntegerObject:on:indent:
  14317.     #cCode:                #generateInlineCCode:on:indent:
  14318.     #cCoerce:to:            #generateCCoercion:on:indent:
  14319.     #preIncrement        #generatePreIncrement:on:indent:
  14320.     #preDecrement        #generatePreDecrement:on:indent:
  14321.     #inline:                #generateInlineDirective:on:indent:
  14322.     #sharedCodeNamed:inCase:    #generateSharedCodeDirective:on:indent:
  14323.     ).
  14324.  
  14325.     1 to: pairs size by: 2 do: [ :i |
  14326.         translationDict at: (pairs at: i) put: (pairs at: i + 1).
  14327.     ].! !
  14328.  
  14329. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14330.  
  14331. CCodeGenerator class
  14332.     instanceVariableNames: ''!
  14333.  
  14334. !CCodeGenerator class methodsFor: 'removing from system' stamp: 'jm 5/16/1998 10:26'!
  14335. removeCompilerMethods
  14336.     "Before removing the C code generator classes from the system, use this method to remove the compiler node methods that support it. This avoids leaving dangling references to C code generator classes in the compiler node classes."
  14337.  
  14338.     ParseNode withAllSubclasses do: [ :nodeClass |
  14339.         nodeClass removeCategory: 'C translation'.
  14340.     ].
  14341.     Smalltalk at: #AbstractSound ifPresent: [:abstractSound |
  14342.          abstractSound class removeCategory: 'primitive generation'].
  14343. ! !
  14344. SwikiAction subclass: #CachedSwikiAction
  14345.     instanceVariableNames: 'cacheDirectory cacheURL pwsURL '
  14346.     classVariableNames: ''
  14347.     poolDictionaries: ''
  14348.     category: 'PluggableWebServer'!
  14349. !CachedSwikiAction commentStamp: 'di 5/22/1998 16:32' prior: 0!
  14350. CachedSwikiAction caches SwikiAction pages so that they can be served as plain HTML files (no embedded Squeak code) even by a native webServer. 
  14351.  
  14352. You must edit three class methods in CachedSwikiAction to get it to serve appropriately.
  14353.  
  14354. * CachedSwikiAction class defaultCacheDirectory is where to store cached pages
  14355. * CachedSwikiAction class defaultCacheURL is the URL to precede cached pages
  14356. * CachedSwikiAction class defaultPWSURL is where the PWS is that can handle editing and searching.
  14357.  
  14358. !
  14359. ]style[(25 12 201 45 34 39 38 37 61)f1,f1LSwikiAction Comment;,f1,f1LCachedSwikiAction class defaultCacheDirectory;,f1,f1LCachedSwikiAction class defaultCacheURL;,f1,f1LCachedSwikiAction class defaultPWSURL;,f1!
  14360.  
  14361.  
  14362. !CachedSwikiAction methodsFor: 'save/restore' stamp: 'mjg 3/18/98 12:44'!
  14363. restore: nameOfSwiki
  14364.     super restore: nameOfSwiki.
  14365.     self source: 'cswiki',(ServerAction pathSeparator).
  14366.     self cacheDirectory: (self class defaultCacheDirectory).
  14367.     self cacheURL: (self class defaultCacheURL).
  14368.     self pwsURL: (self class defaultPWSURL).
  14369.     self generate.
  14370. ! !
  14371.  
  14372. !CachedSwikiAction methodsFor: 'save/restore' stamp: 'mjg 3/23/98 11:35'!
  14373. restoreNoGen: nameOfSwiki
  14374.     super restore: nameOfSwiki.
  14375.     self source: 'cswiki',(ServerAction pathSeparator).
  14376.     self cacheDirectory: (self class defaultCacheDirectory).
  14377.     self cacheURL: (self class defaultCacheURL).
  14378.     self pwsURL: (self class defaultPWSURL).
  14379.     "self generate."
  14380. ! !
  14381.  
  14382.  
  14383. !CachedSwikiAction methodsFor: 'URL processing' stamp: 'mjg 3/18/98 12:41'!
  14384. browse: pageRef from: request
  14385.     "Just reply with a page in HTML format"
  14386.  
  14387.     | formattedPage |
  14388.     formattedPage _ pageRef copy.
  14389.     "Make a copy, then format the text."
  14390.     formattedPage formatted: (HTMLformatter swikify: pageRef text
  14391.             linkhandler: [:link | urlmap
  14392.                     linkForCache: link
  14393.                     from: request peerName
  14394.                     storingTo: OrderedCollection new]).
  14395.     request reply: (HTMLformatter evalEmbedded: (self fileContents: source ,'page.html')
  14396.             with: formattedPage).
  14397. ! !
  14398.  
  14399. !CachedSwikiAction methodsFor: 'URL processing' stamp: 'mjg 3/18/98 12:34'!
  14400. generate
  14401.     1 to: (urlmap pages size) do: [:ref |
  14402.         self generate: (urlmap atID: ref) from: 'Beginning'.].
  14403.     self generateRecent.
  14404. ! !
  14405.  
  14406. !CachedSwikiAction methodsFor: 'URL processing' stamp: 'mjg 3/26/98 12:39'!
  14407. generate: pageRef from: request
  14408.     "Just reply with a page in HTML format"
  14409.  
  14410.     | formattedPage peer cacheFile file|
  14411.     (request isKindOf: PWS) 
  14412.     ifFalse: [(request isKindOf: String) ifTrue: [peer _ request] ifFalse: [peer _ ' ']] 
  14413.     ifTrue: [peer _ request peerName].
  14414.     formattedPage _ pageRef copy.
  14415.     "Make a copy, then format the text."
  14416.     formattedPage formatted: (HTMLformatter swikify: pageRef text
  14417.             linkhandler: [:link | urlmap
  14418.                     linkForCache: link
  14419.                     from: peer
  14420.                     storingTo: OrderedCollection new]).
  14421.     cacheFile _ (self cacheDirectory),(self name),(ServerAction pathSeparator),(pageRef coreID),'.html'.
  14422.     (StandardFileStream isAFileNamed: cacheFile)
  14423.     ifTrue: [FileDirectory deleteFilePath: cacheFile].
  14424.     file _ FileStream fileNamed: cacheFile.
  14425.     file nextPutAll: (HTMLformatter evalEmbedded: (self fileContents: source ,'page.html')
  14426.             with: formattedPage).
  14427.     file close.
  14428.  
  14429. ! !
  14430.  
  14431. !CachedSwikiAction methodsFor: 'URL processing' stamp: 'mjg 3/18/98 12:21'!
  14432. generateRecent
  14433.     | file |
  14434.     file _ FileStream fileNamed: (self cacheDirectory),(self name),(ServerAction pathSeparator),'recent.html'.
  14435.     file nextPutAll: (HTMLformatter evalEmbedded: (self fileContents: source, 'recent.html')
  14436.                     with: urlmap recentCache).
  14437.     file close.! !
  14438.  
  14439. !CachedSwikiAction methodsFor: 'URL processing' stamp: 'mjg 3/23/98 11:44'!
  14440. inputFrom: request
  14441.     "Take user's input and respond with a searchresult or store the edit"
  14442.  
  14443.     | coreRef page |
  14444.     coreRef _ request message size < 2
  14445.         ifTrue: ['1']
  14446.         ifFalse: [request message at: 2].
  14447.     coreRef = 'searchresult' ifTrue: [
  14448.         "If contains search string, do search"
  14449.         request reply: PWS crlf, 
  14450.             (HTMLformatter evalEmbedded: (self fileContents: source, 'results.html')
  14451.                 with: (urlmap searchCacheFor: (request fields at: 'searchFor' ifAbsent: ['nothing']))).
  14452.         ^ #return].
  14453.     (request fields includesKey: 'text') ifTrue: ["It's a response from an edit, so store the page"
  14454.         page _ urlmap
  14455.             storeID: coreRef
  14456.             text: (request fields at: 'text' ifAbsent: ['blank text'])
  14457.             from: request peerName.
  14458.         page user: request userID.  "Address is machine, user only if logged in"
  14459.         self generate: (urlmap atID: coreRef) from: request.
  14460.         self generateRecent.
  14461.         ^ self].    "return self means do serve the edited page afterwards"
  14462.     "oops, a new kind!!"
  14463.     Transcript show: 'Unknown data from client. '; show: request fields printString; cr.! !
  14464.  
  14465.  
  14466. !CachedSwikiAction methodsFor: 'access' stamp: 'mjg 3/18/98 11:39'!
  14467. cacheDirectory
  14468.     ^cacheDirectory! !
  14469.  
  14470. !CachedSwikiAction methodsFor: 'access' stamp: 'mjg 3/18/98 11:39'!
  14471. cacheDirectory: directory
  14472.     cacheDirectory _ directory! !
  14473.  
  14474. !CachedSwikiAction methodsFor: 'access' stamp: 'mjg 3/18/98 11:44'!
  14475. cacheURL
  14476.     ^cacheURL! !
  14477.  
  14478. !CachedSwikiAction methodsFor: 'access' stamp: 'mjg 3/18/98 11:44'!
  14479. cacheURL: urlString
  14480.     cacheURL _ urlString! !
  14481.  
  14482. !CachedSwikiAction methodsFor: 'access' stamp: 'mjg 3/18/98 12:44'!
  14483. pwsURL
  14484.     ^pwsURL    ! !
  14485.  
  14486. !CachedSwikiAction methodsFor: 'access' stamp: 'mjg 3/18/98 12:44'!
  14487. pwsURL: urlString
  14488.     pwsURL _ urlString    ! !
  14489.  
  14490. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  14491.  
  14492. CachedSwikiAction class
  14493.     instanceVariableNames: ''!
  14494.  
  14495. !CachedSwikiAction class methodsFor: 'initialization' stamp: 'tk 5/21/1998 12:58'!
  14496. setUp: named
  14497.     | newAction |
  14498.     super setUp: named.
  14499.     newAction _ PWS actions at: named.
  14500.     newAction cacheDirectory: (self defaultCacheDirectory).
  14501.     newAction cacheURL: (self defaultCacheURL).
  14502.     newAction source: 'cswiki',(ServerAction pathSeparator).
  14503.     ^ newAction! !
  14504.  
  14505.  
  14506. !CachedSwikiAction class methodsFor: 'services' stamp: 'mjg 3/23/98 12:05'!
  14507. defaultCacheDirectory
  14508.     ^'Guz 7600:WebSTAR 2.0:'! !
  14509.  
  14510. !CachedSwikiAction class methodsFor: 'services' stamp: 'mjg 3/23/98 12:05'!
  14511. defaultCacheURL
  14512.     ^'http://guzdial.cc.gatech.edu/'! !
  14513.  
  14514. !CachedSwikiAction class methodsFor: 'services' stamp: 'mjg 3/23/98 12:05'!
  14515. defaultPWSURL
  14516.     ^'http://guzdial.cc.gatech.edu:8080/'! !
  14517. Morph subclass: #CachingMorph
  14518.     instanceVariableNames: 'damageRecorder cacheCanvas '
  14519.     classVariableNames: ''
  14520.     poolDictionaries: ''
  14521.     category: 'Morphic-Kernel'!
  14522. !CachingMorph commentStamp: 'di 5/22/1998 16:32' prior: 0!
  14523. CachingMorph comment:
  14524. 'This morph can be used to cache the picture of a morph that takes a long time to draw. It should be used with judgement, however, since heavy use of caching can consume large amounts of memory.'!
  14525.  
  14526.  
  14527. !CachingMorph methodsFor: 'all'!
  14528. drawOn: aCanvas
  14529.  
  14530.     submorphs isEmpty ifTrue: [^ super drawOn: aCanvas].
  14531. ! !
  14532.  
  14533. !CachingMorph methodsFor: 'all'!
  14534. fullDrawOn: aCanvas
  14535.  
  14536.     self updateCacheCanvasDepth: aCanvas depth.
  14537.     aCanvas image: cacheCanvas form at: self fullBounds origin.
  14538. ! !
  14539.  
  14540. !CachingMorph methodsFor: 'all'!
  14541. imageForm
  14542.  
  14543.     self updateCacheCanvasDepth: Display depth.
  14544.     ^ cacheCanvas form offset: self fullBounds topLeft
  14545. ! !
  14546.  
  14547. !CachingMorph methodsFor: 'all'!
  14548. initialize
  14549.  
  14550.     super initialize.
  14551.     color _ Color veryLightGray.
  14552.     damageRecorder _ DamageRecorder new.
  14553. ! !
  14554.  
  14555. !CachingMorph methodsFor: 'all'!
  14556. invalidRect: damageRect
  14557.     "Record the given rectangle in the damage list."
  14558.  
  14559.     damageRecorder recordInvalidRect: (damageRect translateBy: self fullBounds origin negated).
  14560.     super invalidRect: damageRect.
  14561. ! !
  14562.  
  14563. !CachingMorph methodsFor: 'all' stamp: 'jm 11/13/97 16:31'!
  14564. releaseCachedState
  14565.  
  14566.     super releaseCachedState.
  14567.     cacheCanvas _ nil.
  14568. ! !
  14569.  
  14570. !CachingMorph methodsFor: 'all' stamp: 'jm 7/30/97 12:43'!
  14571. updateCacheCanvasDepth: depth
  14572.     "Update the cached image of the morphs being held by this hand."
  14573.  
  14574.     | myBnds rectList c |
  14575.     myBnds _ self fullBounds.
  14576.     (cacheCanvas == nil or: [cacheCanvas extent ~= myBnds extent]) ifTrue: [
  14577.         cacheCanvas _ FormCanvas extent: myBnds extent depth: depth.
  14578.         c _ cacheCanvas copyOffset: myBnds origin negated.
  14579.         ^ super fullDrawOn: c].
  14580.  
  14581.     "incrementally update the cache canvas"
  14582.     rectList _ damageRecorder invalidRectsFullBounds: (0@0 extent: myBnds extent).
  14583.     damageRecorder reset.
  14584.     rectList do: [:r |
  14585.         c _ cacheCanvas copyOrigin: myBnds origin negated clipRect: r.
  14586.         c fillColor: Color transparent.  "clear to transparent"
  14587.         super fullDrawOn: c].
  14588. ! !
  14589. Object subclass: #Canvas
  14590.     instanceVariableNames: 'origin clipRect shadowDrawing '
  14591.     classVariableNames: ''
  14592.     poolDictionaries: ''
  14593.     category: 'Morphic-Support'!
  14594. !Canvas commentStamp: 'di 5/22/1998 16:32' prior: 0!
  14595. Canvas comment:
  14596. 'A canvas is a two-dimensional medium on which morphs are drawn in a device-independent manner. Canvases keep track of the origin and clipping rectangle, as well as the underlying drawing medium (such as a window, pixmap, or postscript script).
  14597.  
  14598. This kind of canvas does no drawing, and may be used as a "null canvas" to factor out drawing time during performance measurements.'!
  14599.  
  14600.  
  14601. !Canvas methodsFor: 'initialization'!
  14602. reset
  14603.  
  14604.     origin _ 0@0.                            "origin of the top-left corner of this cavas"
  14605.     clipRect _ (0@0 corner: 10000@10000).        "default clipping rectangle"
  14606.     shadowDrawing _ false.                    "draw translucent shadows when true"! !
  14607.  
  14608.  
  14609. !Canvas methodsFor: 'copying' stamp: 'jm 8/2/97 13:54'!
  14610. copy
  14611.  
  14612.     ^ self clone
  14613. ! !
  14614.  
  14615. !Canvas methodsFor: 'copying'!
  14616. copyClipRect: aRectangle
  14617.  
  14618.     ^ self copyOrigin: origin clipRect: (aRectangle translateBy: origin)
  14619. ! !
  14620.  
  14621. !Canvas methodsFor: 'copying'!
  14622. copyForShadowDrawingOffset: aPoint
  14623.  
  14624.     ^ (self copyOrigin: origin + aPoint clipRect: clipRect) setShadowDrawing! !
  14625.  
  14626. !Canvas methodsFor: 'copying'!
  14627. copyOffset: aPoint
  14628.  
  14629.     ^ self copyOrigin: origin + aPoint clipRect: clipRect! !
  14630.  
  14631. !Canvas methodsFor: 'copying'!
  14632. copyOffset: aPoint clipRect: sourceClip
  14633.     "Make a copy of me offset by aPoint, and further clipped
  14634.     by sourceClip, a rectangle in the un-offset coordinates"
  14635.  
  14636.     ^ self copyOrigin: aPoint + origin
  14637.         clipRect: ((sourceClip translateBy: origin) intersect: clipRect)! !
  14638.  
  14639. !Canvas methodsFor: 'copying'!
  14640. copyOrigin: aPoint clipRect: aRectangle
  14641.     "Return a copy of this canvas with the given origin. The clipping rectangle of this canvas is the intersection of the given rectangle and the receiver's current clipping rectangle. This allows the clipping rectangles of nested clipping morphs to be composed."
  14642.  
  14643.     ^ self copy
  14644.         setOrigin: aPoint
  14645.         clipRect: (clipRect intersect: aRectangle)! !
  14646.  
  14647.  
  14648. !Canvas methodsFor: 'accessing'!
  14649. clipRect
  14650.     ^ clipRect translateBy: origin negated! !
  14651.  
  14652. !Canvas methodsFor: 'accessing'!
  14653. depth
  14654.  
  14655.     ^ Display depth
  14656. ! !
  14657.  
  14658. !Canvas methodsFor: 'accessing'!
  14659. origin
  14660.  
  14661.     ^ origin! !
  14662.  
  14663.  
  14664. !Canvas methodsFor: 'testing'!
  14665. isVisible: aRectangle
  14666.     "Optimization of: ^ clipRect intersects: (aRectangle translateBy: origin)"
  14667.  
  14668.     ^ ((aRectangle right + origin x) < clipRect left or:
  14669.       [(aRectangle left + origin x) > clipRect right or:
  14670.       [(aRectangle bottom + origin y) < clipRect top or:
  14671.       [(aRectangle top + origin y) > clipRect bottom]]]) not
  14672. ! !
  14673.  
  14674.  
  14675. !Canvas methodsFor: 'drawing'!
  14676. fillColor: c
  14677.     "Noop here; overridden by non-trivial canvases."! !
  14678.  
  14679. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 13:54'!
  14680. fillOval: r color: c
  14681.  
  14682.     self fillOval: r color: c borderWidth: 0 borderColor: Color transparent.
  14683. ! !
  14684.  
  14685. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 13:54'!
  14686. fillOval: r color: c borderWidth: borderWidth borderColor: borderColor
  14687.     "Noop here; overridden by non-trivial canvases."
  14688. ! !
  14689.  
  14690. !Canvas methodsFor: 'drawing'!
  14691. fillRectangle: r color: c
  14692.     "Noop here; overridden by non-trivial canvases."! !
  14693.  
  14694. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 13:54'!
  14695. frameAndFillRectangle: r fillColor: fillColor borderWidth: borderWidth borderColor: borderColor
  14696.     "Noop here; overridden by non-trivial canvases."
  14697. ! !
  14698.  
  14699. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 13:54'!
  14700. frameAndFillRectangle: r fillColor: fillColor borderWidth: borderWidth topLeftColor: topLeftColor bottomRightColor: bottomRightColor
  14701.     "Noop here; overridden by non-trivial canvases."
  14702. ! !
  14703.  
  14704. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 14:08'!
  14705. frameOval: r color: c
  14706.  
  14707.     self fillOval: r color: Color transparent borderWidth: 1 borderColor: c.
  14708. ! !
  14709.  
  14710. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 14:10'!
  14711. frameOval: r width: w color: c
  14712.  
  14713.     self fillOval: r color: Color transparent borderWidth: w borderColor: c.
  14714. ! !
  14715.  
  14716. !Canvas methodsFor: 'drawing'!
  14717. frameRectangle: r color: c
  14718.  
  14719.     self frameRectangle: r width: 1 color: c.
  14720. ! !
  14721.  
  14722. !Canvas methodsFor: 'drawing'!
  14723. frameRectangle: r width: w color: c
  14724.     "Noop here; overridden by non-trivial canvases."! !
  14725.  
  14726. !Canvas methodsFor: 'drawing'!
  14727. image: i at: aPoint
  14728.     "Noop here; overridden by non-trivial canvases."! !
  14729.  
  14730. !Canvas methodsFor: 'drawing' stamp: 'jm 7/28/97 14:30'!
  14731. image: aForm at: aPoint sourceRect: sourceRect rule: rule
  14732.     "Noop here; overridden by non-trivial canvases."
  14733. ! !
  14734.  
  14735. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 13:54'!
  14736. line: pt1 to: pt2 color: c
  14737.  
  14738.     self line: pt1 to: pt2 width: 1 color: c.
  14739. ! !
  14740.  
  14741. !Canvas methodsFor: 'drawing'!
  14742. line: pt1 to: pt2 width: w color: c
  14743.     "Noop here; overridden by non-trivial canvases."! !
  14744.  
  14745. !Canvas methodsFor: 'drawing'!
  14746. paragraph: paragraph bounds: bounds color: c
  14747.     "Noop here; overridden by non-trivial canvases."! !
  14748.  
  14749. !Canvas methodsFor: 'drawing'!
  14750. point: p color: c
  14751.     "Noop here; overridden by non-trivial canvases."! !
  14752.  
  14753. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 13:54'!
  14754. text: s at: pt font: fontOrNil color: c
  14755.  
  14756.     ^ self text: s bounds: (pt extent: 10000@10000) font: fontOrNil color: c
  14757. ! !
  14758.  
  14759. !Canvas methodsFor: 'drawing' stamp: 'jm 8/2/97 13:54'!
  14760. text: s bounds: boundsRect font: fontOrNil color: c
  14761.     "Draw the given string in the given font and color clipped to the given rectangle. If the font is nil, the default font is used. Noop here; overridden by non-trivial canvases."
  14762. ! !
  14763.  
  14764.  
  14765. !Canvas methodsFor: 'private'!
  14766. setOrigin: aPoint clipRect: aRectangle
  14767.  
  14768.     origin _ aPoint.
  14769.     clipRect _ aRectangle.
  14770. ! !
  14771.  
  14772. !Canvas methodsFor: 'private'!
  14773. setShadowDrawing
  14774.     "Put this canvas into 'shadow drawing' mode, which is used to draw translucent shadows. While in this mode, all drawing operations are done in black through a gray mask. The mask allows some of the underlying pixels to show through, providing a crude sense of transparency."
  14775.  
  14776.     shadowDrawing _ true.! !
  14777. ParseNode subclass: #CascadeNode
  14778.     instanceVariableNames: 'receiver messages '
  14779.     classVariableNames: ''
  14780.     poolDictionaries: ''
  14781.     category: 'System-Compiler'!
  14782. !CascadeNode commentStamp: 'di 5/22/1998 16:32' prior: 0!
  14783. CascadeNode comment: 'The first message has the common receiver, the rest have receiver == nil, which signifies cascading.'!
  14784.  
  14785.  
  14786. !CascadeNode methodsFor: 'initialize-release'!
  14787. receiver: receivingObject messages: msgs
  14788.     " Transcript show: 'abc'; cr; show: 'def' "
  14789.  
  14790.     receiver _ receivingObject.
  14791.     messages _ msgs! !
  14792.  
  14793.  
  14794. !CascadeNode methodsFor: 'code generation'!
  14795. emitForValue: stack on: aStream
  14796.  
  14797.     receiver emitForValue: stack on: aStream.
  14798.     1 to: messages size - 1 do: 
  14799.         [:i | 
  14800.         aStream nextPut: Dup.
  14801.         stack push: 1.
  14802.         (messages at: i) emitForValue: stack on: aStream.
  14803.         aStream nextPut: Pop.
  14804.         stack pop: 1].
  14805.     messages last emitForValue: stack on: aStream! !
  14806.  
  14807. !CascadeNode methodsFor: 'code generation'!
  14808. sizeForValue: encoder
  14809.  
  14810.     | size |
  14811.     size _ (receiver sizeForValue: encoder) + (messages size - 1 * 2).
  14812.     messages do: [:aMessage | size _ size + (aMessage sizeForValue: encoder)].
  14813.     ^size! !
  14814.  
  14815.  
  14816. !CascadeNode methodsFor: 'printing'!
  14817. printOn: aStream indent: level
  14818.     self printOn: aStream indent: level precedence: 0! !
  14819.  
  14820. !CascadeNode methodsFor: 'printing'!
  14821. printOn: aStream indent: level precedence: p
  14822.     | thisPrec |
  14823.     p > 0 ifTrue: [aStream nextPut: $(].
  14824.     thisPrec _ messages first precedence.
  14825.     receiver printOn: aStream indent: level precedence: thisPrec.
  14826.     1 to: messages size do: 
  14827.         [:i | 
  14828.         (messages at: i) printOn: aStream indent: level.
  14829.         i < messages size
  14830.             ifTrue: [aStream nextPut: $;.
  14831.                     thisPrec >= 2 ifTrue: [aStream crtab: level]]].
  14832.     p > 0 ifTrue: [aStream nextPut: $)]! !
  14833.  
  14834.  
  14835. !CascadeNode methodsFor: 'C translation'!
  14836. asTranslatorNode
  14837.     ^TStmtListNode new
  14838.         setArguments: #()
  14839.         statements: (messages collect:
  14840.             [ :msg | msg asTranslatorNode receiver: receiver asTranslatorNode ])! !
  14841. Object subclass: #CautiousModel
  14842.     instanceVariableNames: 'initialExtent '
  14843.     classVariableNames: ''
  14844.     poolDictionaries: ''
  14845.     category: 'Morphic-Support'!
  14846.  
  14847. !CautiousModel methodsFor: 'all' stamp: 'sw 8/15/97 17:20'!
  14848. fullScreenSize
  14849.     "Answer the size to which a window displaying the receiver should be set"
  14850.  
  14851.     ^ (0@0 extent: DisplayScreen actualScreenSize) copy! !
  14852.  
  14853. !CautiousModel methodsFor: 'all' stamp: 'sw 10/2/97 23:16'!
  14854. initialExtent
  14855.     initialExtent ifNotNil: [^ initialExtent].
  14856.     ^ super initialExtent! !
  14857.  
  14858. !CautiousModel methodsFor: 'all' stamp: 'sw 10/2/97 23:16'!
  14859. initialExtent: anExtent
  14860.     initialExtent _ anExtent! !
  14861.  
  14862. !CautiousModel methodsFor: 'all' stamp: 'sw 10/2/97 16:19'!
  14863. okToChange
  14864.     | parms |
  14865.     (parms _ Smalltalk at: #EToyParameters ifAbsent: [nil]) ifNotNil:
  14866.         [parms cautionBeforeClosing ifFalse: [^ true]].
  14867.     Sensor leftShiftDown ifTrue: [^ true].
  14868.  
  14869.     self beep.
  14870.     ^ self confirm: 'Warning!!
  14871. If you answer "yes" here, this
  14872. window will disappear and
  14873. its contents will be lost!!
  14874. Do you really want to do that?'
  14875.  
  14876. "CautiousModel new okToChange"! !
  14877. StringHolder subclass: #ChangeList
  14878.     instanceVariableNames: 'changeList list listIndex listSelections file lostMethodPointer '
  14879.     classVariableNames: ''
  14880.     poolDictionaries: ''
  14881.     category: 'Interface-Changes'!
  14882. !ChangeList commentStamp: 'di 5/22/1998 16:32' prior: 0!
  14883. A ChangeList represents a list of changed methods that reside on a file in fileOut format.  The classes and methods in my list are not necessarily in this image!!  Used as the model for both Version Lists and Changed Methods (in Screen Menu, Changes...).  Note that the two kinds of window have different controller classes!!!!
  14884.  
  14885. It holds three lists:
  14886.     changeList - a list of ChangeRecords
  14887.     list - a list of one-line printable headers
  14888.     listSelections - a list of Booleans (true = selected, false = not selected) multiple OK.
  14889.     listIndex 
  14890. Items that are removed (removeDoits, remove an item) are removed from all three lists.
  14891. Most recently clicked item is the one showing in the bottom pane.!
  14892.  
  14893.  
  14894. !ChangeList methodsFor: 'initialization-release'!
  14895. addItem: item text: text
  14896.     | cr |
  14897.     cr _ Character cr.
  14898.     changeList addLast: item.
  14899.     list addLast: (text collect: [:x | x = cr ifTrue: [$/] ifFalse: [x]])! !
  14900.  
  14901.  
  14902. !ChangeList methodsFor: 'scanning' stamp: 'sw 1/15/98 21:56'!
  14903. scanCategory  
  14904.     "Scan anything that involves more than one chunk; method name is historical only"
  14905.  
  14906.     | itemPosition item tokens stamp isComment anIndex |
  14907.     itemPosition _ file position.
  14908.     item _ file nextChunk.
  14909.  
  14910.     isComment _ (item includesSubString: 'commentStamp:').
  14911.     (isComment or: [item includesSubString: 'methodsFor:']) ifFalse:
  14912.         ["Maybe a preamble, but not one we recognize; bail out with the preamble trick"
  14913.         ^ self addItem: (ChangeRecord new file: file position: itemPosition type: #preamble)
  14914.                  text: ('preamble: ' , item contractTo: 50)].
  14915.  
  14916.     tokens _ Scanner new scanTokens: item.
  14917.     tokens size >= 3 ifTrue:
  14918.         [stamp _ ''.
  14919.         anIndex _ tokens indexOf: #stamp: ifAbsent: [nil].
  14920.         anIndex ifNotNil: [stamp _ tokens at: (anIndex + 1)].
  14921.  
  14922.         tokens second == #methodsFor:
  14923.             ifTrue: [^ self scanCategory: tokens third class: tokens first
  14924.                             meta: false stamp: stamp].
  14925.         tokens third == #methodsFor:
  14926.             ifTrue: [^ self scanCategory: tokens fourth class: tokens first
  14927.                             meta: true stamp: stamp]].
  14928.  
  14929.         tokens second == #commentStamp:
  14930.             ifTrue:
  14931.                 [stamp _ tokens third.
  14932.                 self addItem:
  14933.                         (ChangeRecord new file: file position: file position type: #classComment
  14934.                                         class: tokens first category: nil meta: false stamp: stamp)
  14935.                         text: 'class comment for ' , tokens first, 
  14936.                               (stamp isEmpty ifTrue: [''] ifFalse: ['; ' , stamp]).
  14937.                 file nextChunk.
  14938.                 ^ file skipStyleChunk]! !
  14939.  
  14940. !ChangeList methodsFor: 'scanning' stamp: 'di 1/13/98 16:56'!
  14941. scanCategory: category class: class meta: meta stamp: stamp
  14942.     | itemPosition method |
  14943.     [itemPosition _ file position.
  14944.     method _ file nextChunk.
  14945.     file skipStyleChunk.
  14946.     method size > 0]                        "done when double terminators"
  14947.         whileTrue:
  14948.         [self addItem: (ChangeRecord new file: file position: itemPosition type: #method
  14949.                             class: class category: category meta: meta stamp: stamp)
  14950.             text: 'method: ' , class , (meta ifTrue: [' class '] ifFalse: [' '])
  14951.                 , (Parser new parseSelector: method)
  14952.                 , (stamp isEmpty ifTrue: [''] ifFalse: ['; ' , stamp])]! !
  14953.  
  14954. !ChangeList methodsFor: 'scanning' stamp: 'di 1/13/98 16:57'!
  14955. scanFile: aFile from: startPosition to: stopPosition
  14956.     | itemPosition item prevChar |
  14957.     file _ aFile.
  14958.     changeList _ OrderedCollection new.
  14959.     list _ OrderedCollection new.
  14960.     listIndex _ 0.
  14961.     file position: startPosition.
  14962. 'Scanning changes...'
  14963.     displayProgressAt: Sensor cursorPoint
  14964.     from: startPosition to: stopPosition
  14965.     during: [:bar |
  14966.     [file position < stopPosition]
  14967.         whileTrue:
  14968.         [bar value: file position.
  14969.         [file atEnd not and: [file peek isSeparator]]
  14970.                 whileTrue: [prevChar _ file next].
  14971.         (file peekFor: $!!)
  14972.         ifTrue:
  14973.             [prevChar = Character cr ifTrue: [self scanCategory]]
  14974.         ifFalse:
  14975.             [itemPosition _ file position.
  14976.             item _ file nextChunk.
  14977.             file skipStyleChunk.
  14978.             item size > 0 ifTrue:
  14979.                 [self addItem: (ChangeRecord new file: file position: itemPosition type: #doIt)
  14980.                     text: 'do it: ' , (item contractTo: 50)]]]].
  14981.     listSelections _ Array new: list size withAll: false! !
  14982.  
  14983. !ChangeList methodsFor: 'scanning' stamp: 'di 5/17/1998 12:01'!
  14984. scanVersionsOf: method class: class meta: meta category: category selector: selector
  14985.     | position prevPos prevFileIndex preamble tokens sourceFilesCopy stamp |
  14986.     changeList _ OrderedCollection new.
  14987.     list _ OrderedCollection new.
  14988.     listIndex _ 0.
  14989.     position _ method filePosition.
  14990.     sourceFilesCopy _ SourceFiles collect:
  14991.         [:x | x isNil ifTrue: [ nil ]
  14992.                 ifFalse: [x readOnlyCopy]].
  14993.     method fileIndex == 0 ifTrue: [self inform: 'Not Logged, no versions'.
  14994.                                 ^ nil].
  14995.     file _ sourceFilesCopy at: method fileIndex.
  14996.     [position notNil & file notNil]
  14997.         whileTrue:
  14998.         [file position: (0 max: position-150).  "Skip back to before the preamble"
  14999.         [file position < (position-1)]  "then pick it up from the front"
  15000.             whileTrue: [preamble _ file nextChunk].
  15001.  
  15002.         "Preamble is likely a linked method preamble, if we're in
  15003.             a changes file (not the sources file).  Try to parse it
  15004.             for prior source position and file index"
  15005.         prevPos _ nil.
  15006.         stamp _ ''.
  15007.         (preamble findString: 'methodsFor:' startingAt: 1) > 0
  15008.             ifTrue: [tokens _ Scanner new scanTokens: preamble]
  15009.             ifFalse: [tokens _ Array new  "ie cant be back ref"].
  15010.         ((tokens size between: 7 and: 8)
  15011.             and: [(tokens at: tokens size-5) = #methodsFor:])
  15012.             ifTrue:
  15013.                 [(tokens at: tokens size-3) = #stamp:
  15014.                 ifTrue: ["New format gives change stamp and unified prior pointer"
  15015.                         stamp _ tokens at: tokens size-2.
  15016.                         prevPos _ tokens last.
  15017.                         prevFileIndex _ prevPos // 16r1000000.
  15018.                         prevPos _ prevPos \\ 16r1000000]
  15019.                 ifFalse: ["Old format gives no stamp; prior pointer in two parts"
  15020.                         prevPos _ tokens at: tokens size-2.
  15021.                         prevFileIndex _ tokens last].
  15022.                 (prevPos = 0 or: [prevFileIndex = 0]) ifTrue: [prevPos _ nil]].
  15023.         ((tokens size between: 5 and: 6)
  15024.             and: [(tokens at: tokens size-3) = #methodsFor:])
  15025.             ifTrue:
  15026.                 [(tokens at: tokens size-1) = #stamp:
  15027.                 ifTrue: ["New format gives change stamp and unified prior pointer"
  15028.                         stamp _ tokens at: tokens size]].
  15029.          self addItem:
  15030.                 (ChangeRecord new file: file position: position type: #method
  15031.                         class: class name category: category meta: meta stamp: stamp)
  15032.             text: stamp , ' ' , class name , (meta ifTrue: [' class '] ifFalse: [' ']) , selector.
  15033.         position _ prevPos.
  15034.         prevPos notNil ifTrue:
  15035.             [file _ sourceFilesCopy at: prevFileIndex]].
  15036.     sourceFilesCopy do: [:x | x notNil ifTrue: [x close]].
  15037.     listSelections _ Array new: list size withAll: false! !
  15038.  
  15039. !ChangeList methodsFor: 'scanning' stamp: 'tk 4/24/1998 23:32'!
  15040. toggleListIndex: newListIndex
  15041.  
  15042.     (listIndex ~= 0 and: [listIndex ~= newListIndex]) ifTrue:
  15043.         [listSelections at: listIndex put: false].  "turn off old selection if was on"
  15044.     newListIndex = 0 
  15045.         ifTrue: [listIndex _ 0]
  15046.         ifFalse: [
  15047.             listSelections at: newListIndex  "Complement selection state"
  15048.                     put: (listSelections at: newListIndex) not.
  15049.             listIndex _ (listSelections at: newListIndex)
  15050.                 ifTrue: [newListIndex]  "and set selection index accordingly"
  15051.                 ifFalse: [0]].
  15052.     self changed: #listIndex.
  15053.     self changed: #contents! !
  15054.  
  15055.  
  15056. !ChangeList methodsFor: 'menu actions' stamp: 'jm 5/3/1998 19:15'!
  15057. acceptFrom: aView
  15058.  
  15059.     aView controller text = aView controller initialText ifFalse: [
  15060.         aView flash.
  15061.         ^ self inform: 'You can only accept this version as-is.
  15062. If you want to edit, copy the text to a browser'].
  15063.     (aView setText: aView controller text from: self) ifTrue:
  15064.         [aView ifNotNil: [aView controller accept]].    "initialText"
  15065. ! !
  15066.  
  15067. !ChangeList methodsFor: 'menu actions' stamp: 'tk 4/6/98 11:33'!
  15068. changeListMenu: aMenu
  15069.  
  15070. ^ aMenu labels:
  15071. 'fileIn selections
  15072. fileOut selections...
  15073. select conflicts
  15074. select conflicts with
  15075. select unchanged methods
  15076. select all
  15077. deselect all
  15078. remove doIts
  15079. remove older versions
  15080. remove selections'
  15081.     lines: #(2 6)
  15082.     selections: #(fileInSelections fileOutSelections selectConflicts selectConflictsWith selectUnchangedMethods selectAll deselectAll removeDoIts removeOlderMethodVersions removeSelections)
  15083. ! !
  15084.  
  15085. !ChangeList methodsFor: 'menu actions'!
  15086. deselectAll 
  15087.     listIndex _ 0.
  15088.     listSelections atAllPut: false.
  15089.     self changed: #allSelections! !
  15090.  
  15091. !ChangeList methodsFor: 'menu actions'!
  15092. fileInSelections 
  15093.     listSelections with: changeList do: 
  15094.         [:selected :item | selected ifTrue: [item fileIn]]! !
  15095.  
  15096. !ChangeList methodsFor: 'menu actions' stamp: 'jm 6/12/97 10:54'!
  15097. fileOutSelections 
  15098.     | f |
  15099.     f _ FileStream newFileNamed: (FillInTheBlank request: 'Enter file name' initialAnswer: 'Filename.st').
  15100.     f header; timeStamp.
  15101.     listSelections with: changeList do: 
  15102.         [:selected :item | selected ifTrue: [item fileOutOn: f]].
  15103.     f close.
  15104. ! !
  15105.  
  15106. !ChangeList methodsFor: 'menu actions' stamp: 'tk 4/21/1998 09:56'!
  15107. perform: selector orSendTo: otherTarget
  15108.     "Selector was just chosen from a menu by a user.  If I can respond, then perform it on myself.  If not, send it to otherTarget, presumably the editPane from which the menu was invoked." 
  15109.  
  15110.     (#accept == selector) ifTrue: [^ self acceptFrom: otherTarget view].
  15111.     ^ super perform: selector orSendTo: otherTarget! !
  15112.  
  15113. !ChangeList methodsFor: 'menu actions' stamp: 'tk 4/8/98 12:38'!
  15114. removeDoIts
  15115.     "Remove doits from the receiver, other than initializes. 1/26/96 sw"
  15116.  
  15117.     | newChangeList newList |
  15118.  
  15119.     newChangeList _ OrderedCollection new.
  15120.     newList _ OrderedCollection new.
  15121.  
  15122.     changeList with: list do:
  15123.         [:chRec :str |
  15124.             (chRec type ~~ #doIt or:
  15125.                 [str endsWith: 'initialize'])
  15126.                     ifTrue:
  15127.                         [newChangeList add: chRec.
  15128.                         newList add: str]].
  15129.     newChangeList size < changeList size
  15130.         ifTrue:
  15131.             [changeList _ newChangeList.
  15132.             list _ newList.
  15133.             listIndex _ 0.
  15134.             listSelections _ Array new: list size withAll: false].
  15135.     self changed: #list.
  15136.  
  15137.     ! !
  15138.  
  15139. !ChangeList methodsFor: 'menu actions' stamp: 'di 6/13/97 23:10'!
  15140. removeOlderMethodVersions
  15141.     "Remove older versions of entries from the receiver."
  15142.     | newChangeList newList found str |
  15143.     newChangeList _ OrderedCollection new.
  15144.     newList _ OrderedCollection new.
  15145.     found _ OrderedCollection new.
  15146.  
  15147.     changeList reverseWith: list do:
  15148.         [:chRec :strNstamp | str _ strNstamp copyUpTo: $;.
  15149.             (found includes: str)
  15150.                 ifFalse:
  15151.                     [found add: str.
  15152.                     newChangeList add: chRec.
  15153.                     newList add: strNstamp]].
  15154.     newChangeList size < changeList size
  15155.         ifTrue:
  15156.             [changeList _ newChangeList reversed.
  15157.             list _ newList reversed.
  15158.             listIndex _ 0.
  15159.             listSelections _ Array new: list size withAll: false].
  15160.     self changed: #list! !
  15161.  
  15162. !ChangeList methodsFor: 'menu actions'!
  15163. removeSelections
  15164.     "Remove the selected items from the receiver.  9/18/96 sw"
  15165.  
  15166.     | newChangeList newList |
  15167.  
  15168.     newChangeList _ OrderedCollection new.
  15169.     newList _ OrderedCollection new.
  15170.  
  15171.     1 to: changeList size do:
  15172.         [:i | (listSelections at: i) ifFalse:
  15173.             [newChangeList add: (changeList at: i).
  15174.             newList add: (list at: i)]].
  15175.     newChangeList size < changeList size
  15176.         ifTrue:
  15177.             [changeList _ newChangeList.
  15178.             list _ newList.
  15179.             listIndex _ 0.
  15180.             listSelections _ Array new: list size withAll: false].
  15181.     self changed: #list
  15182.  
  15183.     ! !
  15184.  
  15185. !ChangeList methodsFor: 'menu actions'!
  15186. selectAll
  15187.     listIndex _ 0.
  15188.     listSelections atAllPut: true.
  15189.     self changed: #allSelections! !
  15190.  
  15191. !ChangeList methodsFor: 'menu actions'!
  15192. selectConflicts
  15193.     "Selects all method definitions for which there is ALSO an entry in changes"
  15194.     | change class systemChanges |
  15195.     Cursor read showWhile: 
  15196.     [1 to: changeList size do:
  15197.         [:i | change _ changeList at: i.
  15198.         listSelections at: i put:
  15199.             (change type = #method
  15200.             and: [(class _ change methodClass) notNil
  15201.             and: [(Smalltalk changes atSelector: change methodSelector
  15202.                         class: class) ~~ #none]])]].
  15203.     self changed: #allSelections! !
  15204.  
  15205. !ChangeList methodsFor: 'menu actions'!
  15206. selectConflicts: changeSetOrList
  15207.     "Selects all method definitions for which there is ALSO an entry in the specified changeSet or changList"
  15208.     | change class systemChanges |
  15209.     Cursor read showWhile: 
  15210.     [(changeSetOrList isKindOf: ChangeSet) ifTrue: [
  15211.     1 to: changeList size do:
  15212.         [:i | change _ changeList at: i.
  15213.         listSelections at: i put:
  15214.             (change type = #method
  15215.             and: [(class _ change methodClass) notNil
  15216.             and: [(changeSetOrList atSelector: change methodSelector
  15217.                         class: class) ~~ #none]])]]
  15218.     ifFalse: ["a ChangeList"
  15219.     1 to: changeList size do:
  15220.         [:i | change _ changeList at: i.
  15221.         listSelections at: i put:
  15222.             (change type = #method
  15223.             and: [(class _ change methodClass) notNil
  15224.             and: [changeSetOrList list includes: (list at: i)]])]]
  15225.     ].
  15226.     self changed: #allSelections! !
  15227.  
  15228. !ChangeList methodsFor: 'menu actions' stamp: 'jm 5/22/1998 11:31'!
  15229. selectConflictsWith
  15230.     "Selects all method definitions for which there is ALSO an entry in the specified changeSet or changList chosen by the user. 4/11/96 tk"
  15231.     | aStream all index |
  15232.     aStream _ WriteStream on: (String new: 200).
  15233.     all _ ChangeSet allInstances asOrderedCollection.
  15234.     all do:
  15235.         [:sel | aStream nextPutAll: (sel name contractTo: 40); cr].
  15236.     ChangeList allInstancesDo:
  15237.         [:sel | aStream nextPutAll: (sel file name); cr.
  15238.             all addLast: sel].
  15239.     aStream skip: -1.
  15240.     index _ (PopUpMenu labels: aStream contents) startUp.
  15241.     index > 0 ifTrue: [
  15242.         self selectConflicts: (all at: index)].
  15243. ! !
  15244.  
  15245. !ChangeList methodsFor: 'menu actions' stamp: 'tk 1/7/98 10:12'!
  15246. selectUnchangedMethods
  15247.     "Selects all method definitions for which there is already a method in the current image, whose source is exactly the same.  9/18/96 sw"
  15248.     | change class |
  15249.     Cursor read showWhile: 
  15250.     [1 to: changeList size do:
  15251.         [:i | change _ changeList at: i.
  15252.         listSelections at: i put:
  15253.             ((change type = #method and:
  15254.                 [(class _ change methodClass) notNil]) and:
  15255.                     [(class includesSelector: change methodSelector) and:
  15256.                         [change string = (class sourceCodeAt: change methodSelector) asString]])]].
  15257.     self changed: #allSelections! !
  15258.  
  15259.  
  15260. !ChangeList methodsFor: 'viewing access' stamp: 'sw 1/15/98 22:45'!
  15261. contents
  15262.     ^ listIndex = 0
  15263.         ifTrue: ['']
  15264.         ifFalse: [(changeList at: listIndex) text]! !
  15265.  
  15266. !ChangeList methodsFor: 'viewing access' stamp: 'tk 4/10/1998 09:25'!
  15267. contents: aString
  15268.     listIndex = 0 ifTrue: [self changed: #flash. ^ false].
  15269.     lostMethodPointer ifNotNil: [^ self restoreDeletedMethod].
  15270.     self okToChange "means not dirty" ifFalse: ["is dirty"
  15271.         self inform: 'This is a view of a method on a file.\Please cancel your changes.  You may\accept, but only when the method is untouched.' withCRs.  ^ false].
  15272.         "Can't accept changes here.  Method text must be unchanged!!"
  15273.     (changeList at: listIndex) fileIn.
  15274.     ^ true! !
  15275.  
  15276. !ChangeList methodsFor: 'viewing access'!
  15277. defaultBackgroundColor
  15278.     ^ #lightBlue! !
  15279.  
  15280. !ChangeList methodsFor: 'viewing access'!
  15281. list
  15282.     ^ list! !
  15283.  
  15284. !ChangeList methodsFor: 'viewing access'!
  15285. listIndex
  15286.     ^ listIndex! !
  15287.  
  15288. !ChangeList methodsFor: 'viewing access'!
  15289. listSelectionAt: index
  15290.     ^ listSelections at: index! !
  15291.  
  15292. !ChangeList methodsFor: 'viewing access'!
  15293. listSelectionAt: index put: value
  15294.     listIndex _ 0.
  15295.     ^ listSelections at: index put: value! !
  15296.  
  15297. !ChangeList methodsFor: 'viewing access' stamp: 'di 6/15/97 16:46'!
  15298. restoreDeletedMethod
  15299.     "If lostMethodPointer is not nil, then this is a version browser for a method that has been removed.  In this case we want to establish a sourceCode link to prior versions.  We do this by installing a dummy method with the correct source code pointer prior to installing this version."
  15300.     | dummyMethod class selector |
  15301.     dummyMethod _ CompiledMethod toReturnSelf setSourcePointer: lostMethodPointer.
  15302.     class _ (changeList at: listIndex) methodClass.
  15303.     selector _ (changeList at: listIndex) methodSelector.
  15304.     class addSelector: selector withMethod: dummyMethod.
  15305.     (changeList at: listIndex) fileIn.
  15306.     "IF for some reason, the dummy remains, remove it, but (N.B.!!) we might not get control back if the compile (fileIn above) fails."
  15307.     (class compiledMethodAt: selector) == dummyMethod
  15308.         ifTrue: [class removeSelectorSimply: selector].
  15309.     ^ true! !
  15310.  
  15311. !ChangeList methodsFor: 'viewing access' stamp: 'tk 4/18/1998 09:46'!
  15312. selectedMessageName
  15313.  
  15314.     ^ (changeList at: listIndex) methodSelector
  15315.  
  15316. "
  15317. change _ changeList at: i.
  15318.             ((change type = #method and:
  15319.                 [(class _ change methodClass) notNil]) and:
  15320.                     [(class includesSelector: change methodSelector
  15321. "! !
  15322.  
  15323.  
  15324. !ChangeList methodsFor: 'accessing'!
  15325. changeList
  15326.     ^ changeList! !
  15327.  
  15328. !ChangeList methodsFor: 'accessing'!
  15329. file
  15330.     ^file! !
  15331.  
  15332. !ChangeList methodsFor: 'accessing' stamp: 'di 6/15/97 15:13'!
  15333. setLostMethodPointer: sourcePointer
  15334.     lostMethodPointer _ sourcePointer! !
  15335.  
  15336. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  15337.  
  15338. ChangeList class
  15339.     instanceVariableNames: ''!
  15340.  
  15341. !ChangeList class methodsFor: 'public access' stamp: 'di 5/16/1998 21:53'!
  15342. browseFile: fileName    "ChangeList browseFile: 'AutoDeclareFix.st'"
  15343.     "Opens a changeList on the file named fileName"
  15344.     | changesFile changeList |
  15345.     changesFile _ FileStream readOnlyFileNamed: fileName.
  15346.     Cursor read showWhile:
  15347.         [changeList _ self new
  15348.             scanFile: changesFile from: 0 to: changesFile size].
  15349.     changesFile close.
  15350.     self open: changeList name: fileName , ' log' multiSelect: true! !
  15351.  
  15352. !ChangeList class methodsFor: 'public access' stamp: 'di 5/16/1998 21:53'!
  15353. browseRecent: charCount    "ChangeList browseRecent: 5000"
  15354.     "Opens a changeList on the end of the changes log file"
  15355.     | changesFile changeList end |
  15356.     changesFile _ (SourceFiles at: 2) readOnlyCopy.
  15357.     end _ changesFile size.
  15358.     Cursor read showWhile:
  15359.         [changeList _ self new
  15360.             scanFile: changesFile from: (0 max: end-charCount) to: end].
  15361.     changesFile close.
  15362.     self open: changeList name: 'Recent changes' multiSelect: true! !
  15363.  
  15364. !ChangeList class methodsFor: 'public access'!
  15365. browseRecentLog    "ChangeList browseRecentLog"
  15366.     "Prompt with a menu of how far back to go"
  15367.     | end changesFile banners positions pos chunk i |
  15368.     changesFile _ (SourceFiles at: 2) readOnlyCopy.
  15369.     banners _ OrderedCollection new.
  15370.     positions _ OrderedCollection new.
  15371.     end _ changesFile size.
  15372.     pos _ Smalltalk lastQuitLogPosition.
  15373.     [pos = 0 or: [banners size > 20]] whileFalse:
  15374.         [changesFile position: pos.
  15375.         chunk _ changesFile nextChunk.
  15376.         i _ chunk indexOfSubCollection: 'priorSource: ' startingAt: 1.
  15377.         i > 0 ifTrue: [positions addLast: pos.
  15378.                     banners addLast: (chunk copyFrom: 5 to: i-2).
  15379.                     pos _ Number readFrom: (chunk copyFrom: i+13 to: chunk size)]
  15380.             ifFalse: [pos _ 0]].
  15381.     changesFile close.
  15382.     pos _ (SelectionMenu labelList: banners reversed selections: positions reversed)
  15383.                 startUpWithCaption: 'Browse as far back as...'.
  15384.     pos == nil ifTrue: [^ self].
  15385.     self browseRecent: end-pos! !
  15386.  
  15387. !ChangeList class methodsFor: 'public access' stamp: 'tk 5/19/1998 14:24'!
  15388. browseStream: changesFile
  15389.     "Opens a changeList on a fileStream"
  15390.     | changeList |
  15391.  
  15392.     changesFile readOnly.
  15393.     Cursor read showWhile:
  15394.         [changeList _ self new
  15395.             scanFile: changesFile from: 0 to: changesFile size].
  15396.     changesFile close.
  15397.     self open: changeList name: changesFile localName , ' log' multiSelect: true! !
  15398.  
  15399. !ChangeList class methodsFor: 'public access' stamp: 'di 5/16/1998 21:56'!
  15400. browseVersionsOf: method class: class meta: meta
  15401.         category: category selector: selector 
  15402.     | changeList |
  15403.     Cursor read showWhile:
  15404.         [changeList _ self new
  15405.             scanVersionsOf: method class: class meta: meta
  15406.             category: category selector: selector].
  15407.     changeList ifNotNil:
  15408.         [self open: changeList name: 'Recent versions of ' , selector multiSelect: false]! !
  15409.  
  15410. !ChangeList class methodsFor: 'public access' stamp: 'di 5/16/1998 21:56'!
  15411. browseVersionsOf: method class: class meta: meta
  15412.         category: category selector: selector lostMethodPointer: sourcePointer
  15413.     | changeList |
  15414.     Cursor read showWhile:
  15415.         [changeList _ self new
  15416.             scanVersionsOf: method class: class meta: meta
  15417.             category: category selector: selector].
  15418.     changeList setLostMethodPointer: sourcePointer.
  15419.     self open: changeList name: 'Recent versions of ' , selector multiSelect: false! !
  15420.  
  15421. !ChangeList class methodsFor: 'public access'!
  15422. versionCountForSelector: aSelector class: aClass
  15423.     "Answer the number of versions known to the system for the given class and method, including the current version.  A result of greater than one means that there is at least one superseded version.  6/28/96 sw"
  15424.     
  15425.     | method |
  15426.     method _ aClass compiledMethodAt: aSelector.
  15427.     ^ (self new
  15428.             scanVersionsOf: method class: aClass meta: aClass isMeta
  15429.             category: nil selector: aSelector) list size! !
  15430.  
  15431.  
  15432. !ChangeList class methodsFor: 'instance creation' stamp: 'di 5/17/1998 22:49'!
  15433. open: aChangeList name: aString multiSelect: multiSelect
  15434.     "Create a standard system view for the messageSet, whose label is aString.
  15435.     The listView may be either single or multiple selection type"
  15436.     | topView aBrowserCodeView aListView |
  15437.  
  15438.     World ifNotNil: [^ self openAsMorph: aChangeList name: aString multiSelect: multiSelect].
  15439.  
  15440.     topView _ (StandardSystemView new) model: aChangeList.
  15441.     topView label: aString.
  15442.     topView minimumSize: 180 @ 120.
  15443.     topView borderWidth: 1.
  15444.  
  15445.     aListView _ (multiSelect ifTrue: [PluggableListViewOfMany]
  15446.                             ifFalse: [PluggableListView])
  15447.         on: aChangeList list: #list
  15448.         selected: #listIndex changeSelected: #toggleListIndex:
  15449.         menu: #changeListMenu:
  15450.         keystroke: #messageListKey:from:.
  15451.     aListView window: (0 @ 0 extent: 180 @ 100).
  15452.     topView addSubView: aListView.
  15453.  
  15454.     aBrowserCodeView _ PluggableTextView on: aChangeList 
  15455.             text: #contents accept: #contents:
  15456.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  15457.     aBrowserCodeView controller: ReadOnlyTextController new.
  15458.     aBrowserCodeView window: (0 @ 0 extent: 180 @ 300).
  15459.     topView addSubView: aBrowserCodeView below: aListView.
  15460.     topView controller open! !
  15461.  
  15462. !ChangeList class methodsFor: 'instance creation' stamp: 'di 5/16/1998 22:15'!
  15463. openAsMorph: aChangeList name: labelString multiSelect: multiSelect
  15464.     "Open a morphic view for the messageSet, whose label is labelString.
  15465.     The listView may be either single or multiple selection type"
  15466.     | window listView textMorph |
  15467.     window _ (SystemWindow labelled: labelString) model: aChangeList.
  15468.  
  15469.     window addMorph: (listView _ PluggableListMorph on: aChangeList list: #list
  15470.         selected: #listIndex changeSelected: #toggleListIndex:
  15471.         menu: #changeListMenu: keystroke: #messageListKey:from:)
  15472.         frame: (0@0 corner: 1@0.3).
  15473. "
  15474.     multiSelect ifTrue: [listView controller: PluggableListControllerOfMany new].
  15475. "
  15476.     window addMorph: (textMorph _ PluggableTextMorph on: aChangeList 
  15477.             text: #contents accept: #contents:
  15478.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:)
  15479.         frame: (0@0.3 corner: 1@1).
  15480. "
  15481.     textMorph controller: ReadOnlyTextController new.
  15482. "
  15483.     ^ window openInWorld! !
  15484. Object subclass: #ChangeRecord
  15485.     instanceVariableNames: 'file position type class category meta stamp '
  15486.     classVariableNames: ''
  15487.     poolDictionaries: ''
  15488.     category: 'Interface-Changes'!
  15489. !ChangeRecord commentStamp: 'di 5/22/1998 16:32' prior: 0!
  15490. ChangeRecord comment:
  15491. 'A ChangeRecord represents a change recorded on a file in fileOut format.
  15492. It includes a type (more needs to be done here), and additional information
  15493. for certain types such as method defs which need class and category.'!
  15494.  
  15495.  
  15496. !ChangeRecord methodsFor: 'access' stamp: 'sw 1/15/98 22:46'!
  15497. fileIn
  15498.     | methodClass |
  15499.     Cursor read showWhile:
  15500.         [(methodClass _ self methodClass) notNil ifTrue:
  15501.             [methodClass compile: self text classified: category withStamp: stamp notifying: nil].
  15502.         (type == #doIt) ifTrue:
  15503.             [Compiler evaluate: self string].
  15504.         (type == #classComment) ifTrue:
  15505.             [(Smalltalk at: class asSymbol) comment: self text]]! !
  15506.  
  15507. !ChangeRecord methodsFor: 'access' stamp: 'sw 1/15/98 22:09'!
  15508. fileOutOn: f
  15509.     type == #method
  15510.         ifTrue:
  15511.             [f nextPut: $!!.
  15512.             f nextChunkPut: class asString
  15513.                     , (meta ifTrue: [' class methodsFor: ']
  15514.                             ifFalse: [' methodsFor: '])
  15515.                     , category asString printString.
  15516.             f cr].
  15517.  
  15518.     type == #preamble ifTrue: [f nextPut: $!!].
  15519.  
  15520.     type == #classComment
  15521.         ifTrue:
  15522.             [f nextPut: $!!.
  15523.             f nextChunkPut: class asString, ' commentStamp: ', stamp storeString.
  15524.             f cr].
  15525.  
  15526.     f nextChunkPut: self string.
  15527.     type == #method ifTrue: [f nextChunkPut: ' '].
  15528.     f cr! !
  15529.  
  15530. !ChangeRecord methodsFor: 'access'!
  15531. methodClass 
  15532.     | methodClass |
  15533.     type == #method ifFalse: [^ nil].
  15534.     (Smalltalk includesKey: class asSymbol) ifFalse: [^ nil].
  15535.     methodClass _ Smalltalk at: class asSymbol.
  15536.     meta ifTrue: [^ methodClass class]
  15537.         ifFalse: [^ methodClass]! !
  15538.  
  15539. !ChangeRecord methodsFor: 'access'!
  15540. methodSelector
  15541.     type == #method ifFalse: [^ nil].
  15542.     ^ Parser new parseSelector: self string! !
  15543.  
  15544. !ChangeRecord methodsFor: 'access' stamp: '6/6/97 08:56 dhhi'!
  15545. stamp
  15546.     ^ stamp! !
  15547.  
  15548. !ChangeRecord methodsFor: 'access' stamp: 'di 1/13/98 16:57'!
  15549. string 
  15550.     | string |
  15551.     file openReadOnly.
  15552.     file position: position.
  15553.     string _ file nextChunk.
  15554.     file close.
  15555.     ^ string! !
  15556.  
  15557. !ChangeRecord methodsFor: 'access' stamp: 'sw 1/15/98 22:35'!
  15558. text
  15559.     | text |
  15560.     file openReadOnly.
  15561.     file position: position.
  15562.     text _ file nextChunkText.
  15563.     file close.
  15564.     ^ text! !
  15565.  
  15566. !ChangeRecord methodsFor: 'access'!
  15567. type
  15568.     ^ type! !
  15569.  
  15570.  
  15571. !ChangeRecord methodsFor: 'initialization'!
  15572. file: f position: p type: t
  15573.     file _ f.
  15574.     position _ p.
  15575.     type _ t! !
  15576.  
  15577. !ChangeRecord methodsFor: 'initialization' stamp: '6/6/97 08:48 dhhi'!
  15578. file: f position: p type: t class: c category: cat meta: m stamp: s
  15579.     self file: f position: p type: t.
  15580.     class _ c.
  15581.     category _ cat.
  15582.     meta _ m.
  15583.     stamp _ s! !
  15584. Object subclass: #ChangeSet
  15585.     instanceVariableNames: 'classChanges methodChanges classRemoves methodRemoves name preamble postscript '
  15586.     classVariableNames: ''
  15587.     poolDictionaries: ''
  15588.     category: 'Interface-Changes'!
  15589. !ChangeSet commentStamp: 'di 5/22/1998 16:32' prior: 0!
  15590. ChangeSet comment:
  15591. 'My instances keep track of the changes made to a system, so the user can make an incremental fileOut. The order in which changes are made is not remembered.
  15592.  
  15593. classChanges:  Dictionary {class name -> Set {eg, #change, #rename, etc}}.
  15594. methodChanges:  Dictionary {class name -> IdentityDictionary {selector -> {eg, #change, #remove, etc}}.
  15595. classRemoves:  Set {class name (original)}.
  15596. methodRemoves:  Dictionary {(Array with: class name with: selector) -> (Array with: source pointer with: category)}.
  15597. name: a String used to name the changeSet, and thus any associated project or fileOut.
  15598. preamble and postscript:  two strings that serve as prefix (useful for documentation) and suffix (useful for doits) to the fileout of the changeSet.'!
  15599.  
  15600.  
  15601. !ChangeSet methodsFor: 'initialize-release' stamp: 'sw 11/26/96'!
  15602. clear 
  15603.     "Reset the receiver to be empty.  "
  15604.  
  15605.     classChanges _ Dictionary new.
  15606.     methodChanges _ Dictionary new.
  15607.     classRemoves _ Set new.
  15608.     preamble _ nil.
  15609.     postscript _ nil! !
  15610.  
  15611. !ChangeSet methodsFor: 'initialize-release' stamp: 'tk 5/4/1998 16:41'!
  15612. editPostscript
  15613.     "edit the receiver's postscript, in a separate window.  "
  15614.  
  15615.     self assurePostscriptExists.
  15616.     postscript openLabel: 'Postscript for ChangeSet named ', name! !
  15617.  
  15618. !ChangeSet methodsFor: 'initialize-release' stamp: 'di 5/21/1998 20:50'!
  15619. initialize 
  15620.     "Reset the receiver to be empty."
  15621.  
  15622.     self wither.  "Avoid duplicate entries in AllChangeSets if initialize gets called twice"
  15623.     name _ ChangeSet defaultName! !
  15624.  
  15625. !ChangeSet methodsFor: 'initialize-release'!
  15626. isMoribund
  15627.     "Answer whether the receiver is obsolete and about to die; part of an effort to get such guys cleared out from the change sorter.  2/7/96 sw"
  15628.  
  15629.     ^ name == nil ! !
  15630.  
  15631. !ChangeSet methodsFor: 'initialize-release' stamp: 'di 5/21/1998 20:50'!
  15632. wither
  15633.     "The receiver is to be clobbered.  Clear it out.  2/7/96 sw"
  15634.  
  15635.     classChanges _ Dictionary new.
  15636.     methodChanges _ Dictionary new.
  15637.     classRemoves _ Set new.
  15638.     methodRemoves _ Dictionary new.
  15639.     name _ nil! !
  15640.  
  15641.  
  15642. !ChangeSet methodsFor: 'testing' stamp: 'jm 5/22/1998 11:33'!
  15643. belongsToAProject
  15644.  
  15645.     Project allInstancesDo: [:proj |
  15646.         proj projectChangeSet == self ifTrue: [^ true]].
  15647.     ^ false
  15648. ! !
  15649.  
  15650. !ChangeSet methodsFor: 'testing' stamp: 'tk 5/7/1998 12:57'!
  15651. classChangeAt: className
  15652.     "Return what we know about class changes to this class."
  15653.     | this |
  15654.  
  15655.     this _ classChanges at: className ifAbsent: [Set new].
  15656.     (classRemoves includes: className) ifTrue: [this add: #remove].
  15657.     ^ this! !
  15658.  
  15659. !ChangeSet methodsFor: 'testing'!
  15660. classRemoves
  15661.     ^ classRemoves! !
  15662.  
  15663. !ChangeSet methodsFor: 'testing'!
  15664. isEmpty
  15665.     "Answer whether the receiver contains any elements."
  15666.  
  15667.     ^(methodChanges isEmpty and: [classChanges isEmpty]) and: [classRemoves isEmpty]! !
  15668.  
  15669. !ChangeSet methodsFor: 'testing'!
  15670. methodChangesAtClass: className
  15671.     "Return what we know about method changes to this class."
  15672.     ^ methodChanges at: className ifAbsent: [Dictionary new].! !
  15673.  
  15674. !ChangeSet methodsFor: 'testing'!
  15675. name
  15676.     "The name of this changeSet.
  15677.      2/7/96 sw: If name is nil, we've got garbage.  Help to identify."
  15678.  
  15679.     ^ name == nil
  15680.         ifTrue:
  15681.             ['<no name -- garbage?>']
  15682.         ifFalse:
  15683.             [name]! !
  15684.  
  15685. !ChangeSet methodsFor: 'testing' stamp: 'sw 10/1/97 17:59'!
  15686. okayToRemove
  15687.     | aName |
  15688.     aName _ self name.
  15689.     self == Smalltalk changes ifTrue:
  15690.         [self inform: 'Cannot remove "', aName, '"
  15691. because it is the 
  15692. current change set.'.
  15693.         ^ false].
  15694.  
  15695.     self belongsToAProject ifTrue:
  15696.         [self inform: 'Cannot remove "', aName, '" 
  15697. because it belongs to a 
  15698. project.'.
  15699.             ^ false].
  15700.  
  15701.     ^ true
  15702. ! !
  15703.  
  15704.  
  15705. !ChangeSet methodsFor: 'converting'!
  15706. asSortedCollection
  15707.     "Answer a SortedCollection whose elements are the elements of the 
  15708.     receiver. The sort order is the default less than or equal ordering."
  15709.     | result |
  15710.     result _ SortedCollection new.
  15711.     classChanges associationsDo: 
  15712.         [:clAssoc | 
  15713.         clAssoc value do: 
  15714.             [:changeType | result add: clAssoc key, ' - ', changeType]].
  15715.     methodChanges associationsDo: 
  15716.         [:clAssoc | 
  15717.         clAssoc value associationsDo: 
  15718.             [:mAssoc | result add: clAssoc key, ' ', mAssoc key, ' - ', mAssoc value]].
  15719.     classRemoves do:
  15720.         [:cName | result add: cName  , ' - ', 'remove'].
  15721.     ^ result! !
  15722.  
  15723.  
  15724. !ChangeSet methodsFor: 'change management' stamp: 'di 5/6/1998 16:39'!
  15725. absorbChangesInChangeSetsNamed: nameList
  15726.     "Absorb into the receiver all the changes found in change sets of the given names.  *** classes renamed in aChangeSet may have have problems"
  15727.  
  15728.     | aChangeSet |
  15729.     nameList do:
  15730.         [:aName | (aChangeSet _ ChangeSorter changeSetNamed: aName) ~~ nil
  15731.             ifTrue:
  15732.                 [self assimilateAllChangesFoundIn: aChangeSet]]! !
  15733.  
  15734. !ChangeSet methodsFor: 'change management'!
  15735. addClass: class 
  15736.     "Include indication that a new class was created."
  15737.  
  15738.     self atClass: class add: #add! !
  15739.  
  15740. !ChangeSet methodsFor: 'change management' stamp: 'tk 5/7/1998 13:24'!
  15741. assimilateAllChangesFoundIn: aChangeSet
  15742.     "Make all changes in aChangeSet take effect on self as if they happened just now.  *** classes renamed in aChangeSet may have have problems"
  15743.  
  15744.     | cls info selector pair |
  15745.     aChangeSet changedClassNames do: [:className |
  15746.       (cls _ Smalltalk classNamed: className) ifNotNil:
  15747.         [info _ aChangeSet classChangeAt: className.
  15748.         info do: [:each | self atClass: cls add: each].
  15749.  
  15750.         info _ aChangeSet methodChanges at: className 
  15751.             ifAbsent: [Dictionary new].
  15752.         info associationsDo: [:assoc |
  15753.             assoc value == #remove
  15754.                 ifTrue:
  15755.                     [selector _ assoc key.
  15756.                     self removeSelector: selector class: cls.
  15757.                     pair _ aChangeSet methodRemoves
  15758.                             at: (Array with: cls name with: selector)
  15759.                             ifAbsent: [nil].
  15760.                     pair ifNotNil:
  15761.                         ["Retain source code ref if stored"
  15762.                         methodRemoves at: (Array with: cls name with: selector)
  15763.                                         put: pair]]
  15764.                 ifFalse: 
  15765.                     [self atSelector: assoc key class: cls put: assoc value]]]].
  15766.         classRemoves addAll: aChangeSet classRemoves.    "names of them"
  15767. ! !
  15768.  
  15769. !ChangeSet methodsFor: 'change management'!
  15770. changeClass: class 
  15771.     "Include indication that a class definition has been changed. 
  15772.      6/10/96 sw: don't accumulate this information for classes that don't want logging
  15773.      7/12/96 sw: use wantsChangeSetLogging flag"
  15774.  
  15775.     class wantsChangeSetLogging
  15776.         ifTrue:
  15777.             [self atClass: class add: #change]! !
  15778.  
  15779. !ChangeSet methodsFor: 'change management'!
  15780. changedClasses
  15781.     "Answer a OrderedCollection of changed or edited classes.  Not including removed classes.  Sort alphabetically by name."
  15782.  
  15783.     "Much faster to sort names first, then convert back to classes.  Because metaclasses reconstruct their name at every comparison in the sorted collection.
  15784.     8/91 sw chgd to filter out non-existent classes (triggered by problems with class-renames"
  15785.     classChanges == nil ifTrue: [^ OrderedCollection new].
  15786.     ^ self changedClassNames collect: 
  15787.         [:className | Smalltalk classNamed: className]
  15788.             thenSelect:
  15789.                 [:aClass | aClass notNil]! !
  15790.  
  15791. !ChangeSet methodsFor: 'change management' stamp: 'tk 5/7/1998 12:55'!
  15792. changedClassNames
  15793.     "Answer a OrderedCollection of the names of changed or edited classes.  DOES include removed classes.  Sort alphabetically."
  15794.  
  15795.     | classes |
  15796.     classes _ SortedCollection new: (methodChanges size + classChanges size) *2.
  15797.     methodChanges keys do: [:className | classes add: className].
  15798.     classChanges keys do: [:className | 
  15799.         (methodChanges includesKey: className) ifFalse: [
  15800.             "avoid duplicates, faster than (classes addIfNotPresent: xx)"
  15801.             classes add: className]].
  15802.     classRemoves do: [:className | classes addIfNotPresent: className].
  15803.     ^ classes asOrderedCollection! !
  15804.  
  15805. !ChangeSet methodsFor: 'change management'!
  15806. commentClass: class 
  15807.     "Include indication that a class comment has been changed."
  15808.  
  15809.     self atClass: class add: #comment! !
  15810.  
  15811. !ChangeSet methodsFor: 'change management'!
  15812. flushClassRemoves
  15813.     classRemoves _ Set new! !
  15814.  
  15815. !ChangeSet methodsFor: 'change management' stamp: 'sw 5/21/1998 18:30'!
  15816. forgetAllChangesFoundIn: aChangeSet
  15817.     "Remove from the receiver all method changes found in aChangeSet. The intention is facilitate the process of factoring a large set of changes into disjoint change sets.  To use:  in a change sorter, copy over all the changes you want into some new change set, then use the subtract-other-side feature to subtract those changes from the larger change set, and continue in this manner.  (But, remember that if a changeSet says #add, but the method is missing in the image, it won't file out!!)"
  15818.     | cls itsMethodChanges |
  15819.     aChangeSet == self ifTrue: [^ self].
  15820.  
  15821.     aChangeSet changedClassNames do: 
  15822.         [:className | (cls _ Smalltalk classNamed: className) ~~ nil ifTrue:
  15823.                 [itsMethodChanges _ aChangeSet methodChanges at: className 
  15824.                         ifAbsent: [Dictionary new].
  15825.                 itsMethodChanges associationsDo:
  15826.                     [:assoc | self undoChange: assoc value for: assoc key class: cls].
  15827.                         "try to undo the change found in aChangeSet"
  15828.                 (aChangeSet hasClassChangesFor: className) ifTrue:
  15829.                     [self removeClassChanges: cls]]].
  15830.     classRemoves removeAllFoundIn: aChangeSet classRemoves.    "names of them"
  15831. ! !
  15832.  
  15833. !ChangeSet methodsFor: 'change management' stamp: 'sw 2/3/98 14:21'!
  15834. hasClassChangesFor: aKey
  15835.     ^ classChanges includesKey: aKey! !
  15836.  
  15837. !ChangeSet methodsFor: 'change management' stamp: 'sw 9/17/97 20:47'!
  15838. noteRemovalOf: aClass
  15839.     "The class is about to be removed from the system.  Adjust the receiver to reflect that fact."
  15840.  
  15841.     classChanges removeKey: aClass name ifAbsent: [].
  15842.     methodChanges removeKey: aClass name ifAbsent: [].
  15843.     classChanges removeKey: aClass class name ifAbsent: [].
  15844.     methodChanges removeKey: aClass class name ifAbsent: [].
  15845.     classRemoves add: aClass name! !
  15846.  
  15847. !ChangeSet methodsFor: 'change management'!
  15848. removeClassAndMetaClassChanges: class
  15849.     "Remove all memory of changes associated with this class and its metaclass.  7/18/96 sw"
  15850.  
  15851.     classChanges removeKey: class name ifAbsent: [].
  15852.     methodChanges removeKey: class name ifAbsent: [].
  15853.     classChanges removeKey: class class name ifAbsent: [].
  15854.     methodChanges removeKey: class class name ifAbsent: [].
  15855.     classRemoves remove: class name ifAbsent: [].! !
  15856.  
  15857. !ChangeSet methodsFor: 'change management'!
  15858. removeClassChanges: class
  15859.     "Remove all memory of changes associated with this class"
  15860.  
  15861.     classChanges removeKey: class name ifAbsent: [].
  15862.     methodChanges removeKey: class name ifAbsent: [].
  15863.     classRemoves remove: class name ifAbsent: [].! !
  15864.  
  15865. !ChangeSet methodsFor: 'change management'!
  15866. renameClass: class as: newName 
  15867.     "Include indication that a class has been renamed."
  15868.  
  15869.     | value |
  15870.     (self atClass: class includes: #rename) ifFalse:
  15871.         [self atClass: class add: 'oldName: ', class name.     "only original name matters"
  15872.         self atClass: class add: #rename].
  15873.      "copy changes using new name (metaclass too)"
  15874.     (Array with: classChanges with: methodChanges) do:
  15875.         [:changes |
  15876.         (value _ changes at: class name ifAbsent: [nil]) == nil ifFalse:
  15877.             [changes at: newName put: value.
  15878.             changes removeKey: class name].
  15879.         (value _ changes at: class class name ifAbsent: [nil]) == nil ifFalse:
  15880.             [changes at: (newName, ' class') put: value.
  15881.             changes removeKey: class class name]]! !
  15882.  
  15883. !ChangeSet methodsFor: 'change management'!
  15884. reorganizeClass: class 
  15885.     "Include indication that a class was reorganized."
  15886.  
  15887.     self atClass: class add: #reorganize! !
  15888.  
  15889.  
  15890. !ChangeSet methodsFor: 'method changes'!
  15891. addSelector: selector class: class 
  15892.     "Include indication that a method has been added.
  15893.      5/16/96 sw: tell Utilities of the change so it can put up an in-order browser on recent submissions."
  15894.  
  15895.     Utilities noteMethodSubmission: selector forClass: class name.
  15896.     self atSelector: selector class: class put: #add! !
  15897.  
  15898. !ChangeSet methodsFor: 'method changes'!
  15899. allMessagesForAddedClasses
  15900.     | messageList  mAssoc |
  15901.     "Smalltalk changes allMessagesForAddedClasses"
  15902.     messageList _ SortedCollection new.
  15903.     classChanges associationsDo:
  15904.         [:clAssoc |
  15905.         (clAssoc value includes: #add)
  15906.             ifTrue:
  15907.                 [(Smalltalk at: clAssoc key) selectorsDo:
  15908.                     [:aSelector | 
  15909.                         messageList add: clAssoc key asString, ' ' , aSelector].
  15910.                 (Smalltalk at: clAssoc key) class selectorsDo:
  15911.                     [:aSelector | 
  15912.                         messageList add: clAssoc key asString, ' class ' , aSelector]]].
  15913.     ^ messageList asArray! !
  15914.  
  15915. !ChangeSet methodsFor: 'method changes'!
  15916. browseMessagesWithPriorVersions
  15917.     "Open a message list browser on the new and changed methods in the receiver which have at least one prior version.  6/28/96 sw"
  15918.  
  15919.     | aList aSelector aClass |
  15920.  
  15921.     aList _ self changedMessageListAugmented select:
  15922.         [:msg |  Utilities setClassAndSelectorFrom: msg in: 
  15923.                 [:cl :sl | aClass _ cl.  aSelector _ sl].
  15924.             (ChangeList versionCountForSelector: aSelector class: aClass) > 1].
  15925.     aList size > 0 ifFalse: [self inform: 'None!!'.  ^ nil].
  15926.     Smalltalk browseMessageList: aList name: (self name, ' methods that have prior versions')! !
  15927.  
  15928. !ChangeSet methodsFor: 'method changes'!
  15929. changedMessageList
  15930.     "Used by a message set browser to access the list view information."
  15931.  
  15932.     | messageList |
  15933.     messageList _ SortedCollection new.
  15934.     methodChanges associationsDo: 
  15935.         [:clAssoc | 
  15936.         clAssoc value associationsDo: 
  15937.             [:mAssoc |
  15938.             mAssoc value = #remove ifFalse:
  15939.                 [messageList add: clAssoc key asString, ' ' , mAssoc key]]].
  15940.     ^messageList asArray! !
  15941.  
  15942. !ChangeSet methodsFor: 'method changes'!
  15943. changedMessageListAugmented
  15944.     "In addition to changedMessageList, put all messages for all added classes in the ChangeSet."
  15945.     ^ self changedMessageList asArray, self allMessagesForAddedClasses! !
  15946.  
  15947. !ChangeSet methodsFor: 'method changes'!
  15948. changeSelector: selector class: class 
  15949.     "Include indication that a method has been edited. 
  15950.      5/16/96 sw: tell Utilities of the change so it can put up an in-order browser on recent submissions."
  15951.  
  15952.     Utilities noteMethodSubmission: selector forClass: class name.
  15953.     (self atSelector: selector class: class) = #add 
  15954.         ifFalse: [self atSelector: selector class: class put: #change]
  15955.             "Don't forget a method is new just because it's been changed"! !
  15956.  
  15957. !ChangeSet methodsFor: 'method changes' stamp: 'di 9/22/97 13:18'!
  15958. removeSelector: selector class: class 
  15959.     "Include indication that a method has been forgotten."
  15960.  
  15961.     (self atSelector: selector class: class) = #add
  15962.         ifTrue: [self atSelector: selector
  15963.                     class: class
  15964.                     put: #addedThenRemoved]
  15965.         ifFalse: [self atSelector: selector
  15966.                     class: class
  15967.                     put: #remove].
  15968.  
  15969.     (class includesSelector: selector) ifTrue:
  15970.         ["Save the source code pointer and category so can still browse old versions"
  15971.         methodRemoves at: (Array with: class name with: selector)
  15972.             put: (Array with: (class compiledMethodAt: selector) sourcePointer
  15973.                         with: (class whichCategoryIncludesSelector: selector))]! !
  15974.  
  15975. !ChangeSet methodsFor: 'method changes'!
  15976. removeSelectorChanges: selector class: class 
  15977.     "Remove all memory of changes associated with the argument, selector, in 
  15978.     this class."
  15979.  
  15980.     | dictionary |
  15981.     dictionary _ methodChanges at: class name ifAbsent: [^self].
  15982.     dictionary removeKey: selector ifAbsent: [].
  15983.     dictionary isEmpty ifTrue: [methodChanges removeKey: class name]! !
  15984.  
  15985. !ChangeSet methodsFor: 'method changes' stamp: 'sw 10/31/97 23:59'!
  15986. selectorList
  15987.     "answer a set of all the selectors represented in the change set"
  15988.     "Smalltalk changes selectorList"
  15989.     | aList |
  15990.     aList _ OrderedCollection new.
  15991.     methodChanges associationsDo: 
  15992.         [:clAssoc | 
  15993.         clAssoc value associationsDo: 
  15994.             [:mAssoc |
  15995.             (#(remove addedThenRemoved) includes: mAssoc value) ifFalse:
  15996.                 [aList add: mAssoc key]]].
  15997.     ^ aList asSet! !
  15998.  
  15999. !ChangeSet methodsFor: 'method changes'!
  16000. selectorsInClass: aClass
  16001.     "Used by a ChangeSorter to access the list methods."
  16002.     "later include class changes"
  16003.     ^ (methodChanges at: aClass ifAbsent: [^#()]) keys! !
  16004.  
  16005. !ChangeSet methodsFor: 'method changes' stamp: 'tk 5/7/1998 15:26'!
  16006. undoChange: action for: selector class: class 
  16007.     "Try to undo the change.  Remember that if a changeSet says #add, but the method is missing in the image, it won't file out!!
  16008.  
  16009. Current cng:     Add  Remove  Add+Remove
  16010. undo: Add       none  Remove  Remove
  16011. undo: Remove  Add    none     Add
  16012. undo:Add+Rem  none  none     none
  16013. (none means the method is entirely deleted from the changeSet)"
  16014.  
  16015.     | dictionary prev |
  16016.     dictionary _ methodChanges at: class name ifAbsent: [^self].
  16017.     prev _ dictionary at: selector ifAbsent: [^self].
  16018.     action == #addedThenRemoved ifTrue: [
  16019.         dictionary removeKey: selector ifAbsent: [].
  16020.         dictionary isEmpty ifTrue: [methodChanges removeKey: class name].
  16021.         ^ self].
  16022.     action == prev ifTrue: [dictionary removeKey: selector ifAbsent: [].
  16023.         dictionary isEmpty ifTrue: [methodChanges removeKey: class name].
  16024.         ^ self].
  16025.     action == #add ifTrue: [dictionary at: selector put: #remove].
  16026.     action == #remove ifTrue: [dictionary at: selector put: #add].
  16027.     dictionary isEmpty ifTrue: [methodChanges removeKey: class name]!
  16028. ]style[(45 129 40 812)f1b,f1,f1u,f1! !
  16029.  
  16030.  
  16031. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 11/27/96'!
  16032. assurePostscriptExists
  16033.     "Make sure there is a StringHolder holding the postscript.  "
  16034.  
  16035.     postscript == nil ifTrue: [postscript _ StringHolder new contents: '']! !
  16036.  
  16037. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 11/27/96'!
  16038. assurePreambleExists
  16039.     "Make sure there is a StringHolder holding the preamble.  
  16040.      : if it's found to have reverted to empty contents, put up the template"
  16041.  
  16042.     (preamble == nil or: [preamble contents size == 0])
  16043.         ifTrue: [preamble _ StringHolder new contents: self preambleTemplate]! !
  16044.  
  16045. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'tk 5/7/1998 14:23'!
  16046. checkForSlips
  16047.     "Return a collection of method refs with possible debugging code in them."
  16048.     | slips tsRef changes method |
  16049.     slips _ OrderedCollection new.
  16050.     tsRef _ Smalltalk associationAt: #Transcript.
  16051.     self changedClasses do:
  16052.         [:aClass |
  16053.         changes _ methodChanges at: aClass name ifAbsent: [nil].
  16054.         changes ifNotNil:
  16055.             [changes associationsDo: 
  16056.                 [:mAssoc | (#(remove addedThenRemoved) includes: mAssoc value) ifFalse:
  16057.                     [method _ aClass compiledMethodAt: mAssoc key ifAbsent: [nil].
  16058.                     method ifNotNil:
  16059.                         [((method hasLiteral: #halt) or: [method hasLiteral: tsRef])
  16060.                             ifTrue: [slips add: aClass name , ' ' , mAssoc key]]]]]].
  16061.     ^ slips! !
  16062.  
  16063. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'jm 3/27/98 08:26'!
  16064. fileOut
  16065.     "File out the receiver, to a file whose name is a function of the change-set name and of the date and the time."
  16066.     | file slips |
  16067.     Cursor write showWhile: [
  16068.         file _ FileStream newFileNamed:
  16069.             ((self name, FileDirectory dot, Utilities dateTimeSuffix, FileDirectory dot, 'cs')
  16070.                 truncateTo: 27).
  16071.         file header; timeStamp.
  16072.         self fileOutPreambleOn: file.
  16073.         self fileOutOn: file.
  16074.         self fileOutPostscriptOn: file.
  16075.         file trailer; close].
  16076.  
  16077.     Preferences suppressCheckForSlips ifTrue: [^ self].  "Can hard-code that pref if desired"
  16078.  
  16079.     slips _ self checkForSlips.
  16080.     (slips size > 0 and: [self confirm: 'Methods in this fileOut have halts
  16081. or references to the Transcript in them.
  16082. Would you like to browse them?'])
  16083.         ifTrue: [Smalltalk browseMessageList: slips
  16084.                             name: 'References to #halt or Transcript']! !
  16085.  
  16086. !ChangeSet methodsFor: 'fileIn/Out'!
  16087. fileOutChangesFor: class on: stream 
  16088.     "Write out all the changes the receiver knows about this class.
  16089.      5/15/96 sw: altered to call fileOutClassModifications:on: rather than fileOutClassChanges:on:, so that class headers won't go out as part of this process (they no go out at the beginning of the fileout"
  16090.  
  16091.     | changes |
  16092.                     "first file out class changes"
  16093.     self fileOutClassModifications: class on: stream.
  16094.                     "next file out changed methods"
  16095.     changes _ OrderedCollection new.
  16096.     (methodChanges at: class name ifAbsent: [^ self]) associationsDo: 
  16097.         [:mAssoc | 
  16098.         mAssoc value = #remove
  16099.             ifFalse: [changes add: mAssoc key]].
  16100.     changes isEmpty ifFalse: 
  16101.         [class fileOutChangedMessages: changes on: stream.
  16102.         stream cr]! !
  16103.  
  16104. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 9/17/97 21:01'!
  16105. fileOutOn: stream 
  16106.     "Write out all the changes the receiver knows about"
  16107.  
  16108.     | classList |
  16109.     self isEmpty ifTrue: [self notify: 'Warning: no changes to file out'].
  16110.     classList _ ChangeSet superclassOrder: self changedClasses asOrderedCollection.
  16111.     classList do:
  16112.         [:aClass |  "if class defn changed, put it onto the file now"
  16113.             self fileOutClassDefinition: aClass on: stream].
  16114.     classList do:
  16115.         [:aClass |  "nb: he following no longer puts out class headers"
  16116.             self fileOutChangesFor: aClass on: stream].
  16117.     stream cr.
  16118.     classList do:
  16119.         [:aClass |
  16120.         self fileOutPSFor: aClass on: stream].
  16121.     classRemoves do:
  16122.         [:aClassName | stream nextChunkPut: 'Smalltalk removeClassNamed: #', aClassName; cr].! !
  16123.  
  16124. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/7/1998 12:14'!
  16125. fileOutPostscriptOn: stream 
  16126.     "If the receiver has a postscript, put it out onto the stream.  "
  16127.  
  16128.     | aString |
  16129.     ((aString _ self postscriptString) size > 0)
  16130.         ifTrue:
  16131.             [stream nextChunkPut: aString "surroundedBySingleQuotes".
  16132.             stream cr; cr]! !
  16133.  
  16134. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/7/1998 12:15'!
  16135. fileOutPreambleOn: stream 
  16136.     "If the receiver has a preamble, put it out onto the stream.  "
  16137.  
  16138.     | aString |
  16139.     ((aString _ self preambleString) size > 0)
  16140.         ifTrue:
  16141.             [stream nextChunkPut: aString "surroundedBySingleQuotes".
  16142.             stream cr; cr]! !
  16143.  
  16144. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/20/1998 02:59'!
  16145. fileOutPSFor: class on: stream 
  16146.     "Write out removals and initialization for this class."
  16147.  
  16148.     (methodChanges at: class name ifAbsent: [^ self]) associationsDo: [:mAssoc | 
  16149.         (#(remove addedThenRemoved) includes: mAssoc value)
  16150.             ifTrue:
  16151.                 [stream nextChunkPut: class name,
  16152.                     ' removeSelector: ', mAssoc key storeString; cr]
  16153.             ifFalse:
  16154.                 [(mAssoc key = #initialize and: [class isMeta]) ifTrue:
  16155.                     [stream nextChunkPut: class soleInstance name, ' initialize'; cr]]]! !
  16156.  
  16157. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/7/1998 12:16'!
  16158. postscriptString
  16159.     "Answer the string representing the postscript.  "
  16160.  
  16161.     ^ postscript == nil
  16162.         ifTrue:
  16163.             [postscript]
  16164.         ifFalse:
  16165.             [postscript contents asString]! !
  16166.  
  16167. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 11/27/96'!
  16168. postscriptString: aString
  16169.     "Establish aString as the new contents of the postscript.  "
  16170.  
  16171.     postscript _ StringHolder new contents: aString! !
  16172.  
  16173. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 5/7/1998 12:08'!
  16174. preambleString
  16175.     "Answer the string representing the preamble"
  16176.  
  16177.     ^ preamble == nil
  16178.         ifTrue:
  16179.             [preamble]
  16180.         ifFalse:
  16181.             [preamble contents asString]! !
  16182.  
  16183. !ChangeSet methodsFor: 'fileIn/Out' stamp: 'sw 11/27/96'!
  16184. preambleString: aString
  16185.     "Establish aString as the new contents of the preamble.  "
  16186.  
  16187.     preamble _ StringHolder new contents: aString! !
  16188.  
  16189. !ChangeSet methodsFor: 'fileIn/Out'!
  16190. preambleTemplate
  16191.     "Answer a string that will form the default contents for a change set's preamble.  Just a first stab at what the content should be.12/3/96 sw"
  16192.  
  16193.     | aStream |
  16194.     aStream _ ReadWriteStream on: ''.
  16195.     aStream nextPutAll: '"Change Set:'.
  16196.     aStream tab;tab; nextPutAll: self name.
  16197.     aStream cr; nextPutAll: 'Date:'; tab; tab; tab; nextPutAll: Date today printString.
  16198.     aStream cr; nextPutAll: 'Author:'; tab; tab; tab; nextPutAll: 'Your Name'.
  16199.     aStream cr; cr; nextPutAll: '<your descriptive text goes here>"'.
  16200.     ^ aStream contents
  16201. "Smalltalk changes preambleTemplate"! !
  16202.  
  16203.  
  16204. !ChangeSet methodsFor: 'private'!
  16205. atClass: class add: changeType
  16206.  
  16207.     (self isNew: class) ifFalse:     "new classes don't matter"
  16208.         [(classChanges at: class name
  16209.                 ifAbsent: [^classChanges at: class name put:
  16210.                     (Set with: changeType)])
  16211.             add: changeType]! !
  16212.  
  16213. !ChangeSet methodsFor: 'private'!
  16214. atClass: class includes: changeType
  16215.  
  16216.     ^(classChanges at: class name ifAbsent: [^false])
  16217.         includes: changeType! !
  16218.  
  16219. !ChangeSet methodsFor: 'private'!
  16220. atSelector: selector class: class
  16221.  
  16222.     ^(methodChanges at: class name ifAbsent: [^#none])
  16223.         at: selector ifAbsent: [#none]! !
  16224.  
  16225. !ChangeSet methodsFor: 'private'!
  16226. atSelector: selector class: class put: changeType
  16227.     | dict |
  16228.     (self isNew: class) ifTrue: [^self].     "Don't keep method changes for new classes"
  16229.     (selector==#DoIt) | (selector==#DoItIn:) ifTrue: [^self].
  16230.     (methodChanges at: class name
  16231.         ifAbsent: 
  16232.             [dict _ IdentityDictionary new.
  16233.             methodChanges at: class name put: dict.
  16234.             dict])
  16235.         at: selector put: changeType ! !
  16236.  
  16237. !ChangeSet methodsFor: 'private' stamp: 'di 6/28/97 20:34'!
  16238. fileOutClassDefinition: class on: stream 
  16239.     "Write out class definition for the given class on the given stream, if the class definition was added or changed.  5/15/96 sw"
  16240.  
  16241.     ((self atClass: class includes: #add) or: [self atClass: class includes: #change])
  16242.         ifTrue:
  16243.             [stream command: 'H3'; nextChunkPut: class definition; cr; command: '/H3']! !
  16244.  
  16245. !ChangeSet methodsFor: 'private' stamp: 'tk 12/15/97 14:49'!
  16246. fileOutClassModifications: class on: stream 
  16247.     "Write out class mod-- rename, comment, reorg, remove, on the given stream.  Differs from the superseded fileOutClassChanges:on: in that it does not deal with class definitions, and does not file out entire added classes.  
  16248.      : put out a rename indicator that won't halt if class of old name not there."
  16249.  
  16250.     | commentRemoteStr header |
  16251.     (self atClass: class includes: #rename) ifTrue:
  16252.         [stream nextChunkPut: 'Smalltalk renameClassNamed: #', (self oldNameFor: class), ' as: #', class name; cr].
  16253.  
  16254.     (self atClass: class includes: #comment) ifTrue:
  16255.         [commentRemoteStr _ class theNonMetaClass organization commentRemoteStr.
  16256.         commentRemoteStr ifNotNil: [
  16257.             stream cr; nextPut: $!!.    "directly"
  16258.             "Should be saying (file command: 'H3') for HTML, but ignoring it here"
  16259.             header _ String streamContents: [:strm | 
  16260.                 strm nextPutAll: class theNonMetaClass name;
  16261.                 nextPutAll: ' commentStamp: '.
  16262.                 Utilities changeStamp storeOn: strm.
  16263.                 strm nextPutAll: ' prior: '; nextPutAll: '0'].
  16264.             stream nextChunkPut: header; cr.
  16265.  
  16266.             RemoteString
  16267.                 newString: commentRemoteStr text
  16268.                 onFileNumber: nil
  16269.                 toFile: stream.
  16270.             stream cr]].
  16271.  
  16272.     (self atClass: class includes: #reorganize) ifTrue:
  16273.         [class fileOutOrganizationOn: stream.
  16274.         stream cr]! !
  16275.  
  16276. !ChangeSet methodsFor: 'private'!
  16277. inspectMethodChanges
  16278.     methodChanges inspect! !
  16279.  
  16280. !ChangeSet methodsFor: 'private'!
  16281. isNew: class
  16282.     "Answer whether this class was added since the ChangeSet was cleared."
  16283.  
  16284.     (class isKindOf: Metaclass)
  16285.         ifTrue: [^self atClass: class soleInstance includes: #add "check class"]
  16286.         ifFalse: [^self atClass: class includes: #add]! !
  16287.  
  16288. !ChangeSet methodsFor: 'private'!
  16289. oldNameFor: class
  16290.     | cName |
  16291.     cName _ (classChanges at: class name) asOrderedCollection
  16292.                 detect: [:x | 'oldName: *' match: x].
  16293.     ^ (Scanner new scanTokens: cName) last! !
  16294.  
  16295.  
  16296. !ChangeSet methodsFor: 'accessing' stamp: 'tk 5/4/1998 17:00'!
  16297. editPreamble
  16298.     "edit the receiver's preamble, in a separate window.  "
  16299.  
  16300.     self assurePreambleExists.
  16301.     preamble openLabel: 'Preamble for ChangeSet named ', name! !
  16302.  
  16303. !ChangeSet methodsFor: 'accessing'!
  16304. methodChanges
  16305.     ^methodChanges! !
  16306.  
  16307. !ChangeSet methodsFor: 'accessing' stamp: 'di 6/15/97 09:45'!
  16308. methodRemoves
  16309.     ^methodRemoves! !
  16310.  
  16311. !ChangeSet methodsFor: 'accessing'!
  16312. name: anObject
  16313.     name _ anObject! !
  16314.  
  16315. !ChangeSet methodsFor: 'accessing'!
  16316. printOn: aStream
  16317.     "2/7/96 sw: provide the receiver's name in the printout"
  16318.     super printOn: aStream.
  16319.     aStream nextPutAll: ' named ', self name! !
  16320.  
  16321. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  16322.  
  16323. ChangeSet class
  16324.     instanceVariableNames: ''!
  16325.  
  16326. !ChangeSet class methodsFor: 'fileIn/Out'!
  16327. superclassOrder: classes 
  16328.     "Arrange the classes in the collection, classes, in superclass order so the 
  16329.     classes can be properly filed in."
  16330.  
  16331.     | all list i aClass superClass |
  16332.     list _ classes copy.             "list is indexable"
  16333.     all _ OrderedCollection new: list size.
  16334.     [list size > 0]
  16335.         whileTrue: 
  16336.             [aClass _ list first.
  16337.             superClass _ aClass superclass.
  16338.             "Make sure it doesn't have an as yet uncollected superclass"
  16339.             [superClass == nil or: [list includes: superClass]]
  16340.                 whileFalse: [superClass _ superClass superclass].
  16341.             i _ 1.
  16342.             [superClass == nil]
  16343.                 whileFalse: 
  16344.                     [i _ i + 1.
  16345.                     aClass _ list at: i.
  16346.                     superClass _ aClass superclass.
  16347.                     "check as yet uncollected superclass"
  16348.                     [superClass == nil or: [list includes: superClass]]
  16349.                         whileFalse: [superClass _ superClass superclass]].
  16350.             all addLast: aClass.
  16351.             list _ list copyWithout: aClass].
  16352.     ^all! !
  16353.  
  16354.  
  16355. !ChangeSet class methodsFor: 'defaults' stamp: 'di 5/6/1998 16:40'!
  16356. defaultName
  16357.     | namesInUse try |
  16358.     namesInUse _ ChangeSorter gatherChangeSets
  16359.                     collect: [:each | each name].
  16360.     1 to: 999999 do:
  16361.         [:i | try _ 'Unnamed' , i printString.
  16362.         (namesInUse includes: try) ifFalse: [^ try]]! !
  16363. StringHolder subclass: #ChangeSorter
  16364.     instanceVariableNames: 'parent myChangeSet currentClassName currentSelector '
  16365.     classVariableNames: 'AllChangeSets '
  16366.     poolDictionaries: ''
  16367.     category: 'Interface-Changes'!
  16368. !ChangeSorter commentStamp: 'di 5/22/1998 16:32' prior: 0!
  16369. I display a ChangeSet.  Two of me are in a DualChangeSorter.!
  16370.  
  16371.  
  16372. !ChangeSorter methodsFor: 'creation' stamp: 'tk 4/29/1998 10:15'!
  16373. defaultBackgroundColor
  16374.  
  16375.     ^ #lightBlue! !
  16376.  
  16377. !ChangeSorter methodsFor: 'creation' stamp: 'tk 5/12/1998 09:38'!
  16378. open
  16379.     "ChangeSorterPluggable new open"
  16380.     | topView |
  16381.     World ifNotNil: [^ self openAsMorph].
  16382.     Sensor leftShiftDown ifTrue: [^ self openAsMorph].   "testing"
  16383.  
  16384.     topView _ StandardSystemView new.
  16385.     topView model: self.
  16386.     myChangeSet ifNil: [self myChangeSet: Smalltalk changes]. 
  16387.     topView label: self labelString.
  16388.     topView borderWidth: 1; minimumSize: 360@360.
  16389.     self openView: topView offsetBy: 0@0.
  16390.     topView controller open.
  16391. ! !
  16392.  
  16393. !ChangeSorter methodsFor: 'creation' stamp: 'tk 5/12/1998 09:42'!
  16394. openAsMorph
  16395.     "ChangeSorter new openAsMorph"
  16396.     |  window |
  16397.  
  16398.     myChangeSet ifNil: [self myChangeSet: Smalltalk changes]. 
  16399.     window _ (SystemWindow labelled: self labelString) model: self.
  16400.     self openAsMorphIn: window rect: (0@0 extent: 1@1).
  16401.     World ifNil: [^ window openInMVC].  "test"
  16402.     window openInWorld! !
  16403.  
  16404. !ChangeSorter methodsFor: 'creation' stamp: 'tk 5/12/1998 13:17'!
  16405. openAsMorphIn: window rect: rect
  16406.     "Add a set of change sorter views to the given top view offset by the given amount. To create a single change sorter, call this once with an offset of 0@0. To create a dual change sorter, call it twice with offsets of 0@0 and 0.5@0."
  16407.     | buttonView col |
  16408.     contents _ ''.
  16409.     self addDependent: window.        "so it will get changed: #relabel"
  16410.     buttonView _ PluggableButtonMorph
  16411.         on: self
  16412.         getState: #mainButtonState
  16413.         action: #changeSetMenuStart
  16414.         label: #mainButtonName
  16415.         menu: #changeSetMenu:.
  16416.     col _ Color perform: self defaultBackgroundColor.
  16417.     buttonView
  16418.         label: myChangeSet name; 
  16419.         onColor: col offColor: col;
  16420.         triggerOnMouseDown: true; borderColor: window color.
  16421.     window addMorph: buttonView
  16422.         frame: (((0@0 extent: 1.0@0.06) scaleBy: rect extent) translateBy: rect origin).
  16423.  
  16424.     window addMorph: (PluggableListMorphByItem on: self
  16425.             list: #classList
  16426.             selected: #currentClassName
  16427.             changeSelected: #currentClassName:
  16428.             menu: #classMenu:)
  16429.         frame: (((0@0.06 extent: 0.5@0.3) scaleBy: rect extent) translateBy: rect origin).
  16430.  
  16431.     window addMorph: (PluggableListMorphByItem on: self
  16432.             list: #messageList
  16433.             selected: #currentSelector
  16434.             changeSelected: #currentSelector:
  16435.             menu: #messageMenu:shifted:
  16436.             keystroke: #messageListKey:from:)
  16437.         frame: (((0.5@0.06 extent: 0.5@0.3) scaleBy: rect extent) translateBy: rect origin).
  16438.  
  16439.     window addMorph: (PluggableTextMorph on: self 
  16440.             text: #contents accept: #contents:notifying:
  16441.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:)
  16442.         frame: (((0@0.36 corner: 1@1) scaleBy: rect extent) translateBy: rect origin).
  16443. ! !
  16444.  
  16445. !ChangeSorter methodsFor: 'creation' stamp: 'di 5/6/1998 17:25'!
  16446. openView: topView offsetBy: offset
  16447.     "Add a set of change sorter views to the given top view offset by the given amount. To create a single change sorter, call this once with an offset of 0@0. To create a dual change sorter, call it twice with offsets of 0@0 and 360@0."
  16448.     | classView messageView codeView buttonView |
  16449.     contents _ ''.
  16450.     self addDependent: topView.        "so it will get changed: #relabel"
  16451.     buttonView _ PluggableButtonView
  16452.         on: self
  16453.         getState: #mainButtonState
  16454.         action: #changeSetMenuStart
  16455.         label: #mainButtonName
  16456.         menu: #changeSetMenu:.
  16457.     buttonView
  16458.         label: myChangeSet name;
  16459.         triggerOnMouseDown: true; borderWidth: 1; 
  16460.         window: ((0 @ 0 extent: 360 @ 20) translateBy: offset).
  16461.     topView addSubView: buttonView.
  16462.  
  16463.     classView _ PluggableListViewByItem on: self
  16464.         list: #classList
  16465.         selected: #currentClassName
  16466.         changeSelected: #currentClassName:
  16467.         menu: #classMenu:.
  16468.     classView window: (0 @ 0 extent: 180 @ 160).
  16469.     topView addSubView: classView below: buttonView.
  16470.  
  16471.     messageView _ PluggableListViewByItem on: self
  16472.         list: #messageList
  16473.         selected: #currentSelector
  16474.         changeSelected: #currentSelector:
  16475.         menu: #messageMenu:shifted:
  16476.         keystroke: #messageListKey:from:.
  16477.     messageView window: (0 @ 0 extent: 180 @ 160).
  16478.     topView addSubView: messageView toRightOf: classView.
  16479.  
  16480.     codeView _ PluggableTextView on: self 
  16481.             text: #contents accept: #contents:notifying:
  16482.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  16483.     codeView window: (0 @ 0 extent: 360 @ 180).
  16484.     topView addSubView: codeView below: classView.! !
  16485.  
  16486.  
  16487. !ChangeSorter methodsFor: 'access' stamp: 'tk 4/29/1998 08:22'!
  16488. changeSet
  16489.     ^ myChangeSet! !
  16490.  
  16491. !ChangeSorter methodsFor: 'access' stamp: 'tk 4/30/1998 13:37'!
  16492. label
  16493.     ^ self labelString! !
  16494.  
  16495. !ChangeSorter methodsFor: 'access' stamp: 'tk 4/30/1998 14:03'!
  16496. labelString
  16497.     "The label for my entire window.  The large button that displays my name is gotten via mainButtonName"
  16498.     ^ parent 
  16499.         ifNil: [Smalltalk changes == myChangeSet
  16500.             ifTrue: ['Changes go to "', myChangeSet name, '"']
  16501.             ifFalse: ['ChangeSet: ', myChangeSet name]]
  16502.         ifNotNil: ['Changes go to "', (Smalltalk changes name), '"']! !
  16503.  
  16504. !ChangeSorter methodsFor: 'access' stamp: 'tk 4/24/1998 09:10'!
  16505. myChangeSet
  16506.     ^ myChangeSet! !
  16507.  
  16508. !ChangeSorter methodsFor: 'access' stamp: 'tk 4/24/1998 08:43'!
  16509. myChangeSet: anObject
  16510.     myChangeSet _ anObject! !
  16511.  
  16512. !ChangeSorter methodsFor: 'access' stamp: 'tk 4/24/1998 08:42'!
  16513. parent
  16514.     ^ parent! !
  16515.  
  16516. !ChangeSorter methodsFor: 'access' stamp: 'tk 4/24/1998 08:42'!
  16517. parent: anObject
  16518.     parent _ anObject! !
  16519.  
  16520. !ChangeSorter methodsFor: 'access' stamp: 'tk 5/19/1998 16:23'!
  16521. showChangeSet: chgSet
  16522.  
  16523.     myChangeSet == chgSet ifFalse: [
  16524.         myChangeSet _ chgSet.
  16525.         currentClassName _ nil.
  16526.         currentSelector _ nil].
  16527.     self changed: #relabel.
  16528.     self changed: #mainButtonName.
  16529.     self changed: #classList.
  16530.     self changed: #messageList.
  16531.     self setContents.
  16532.     self changed: #contents.! !
  16533.  
  16534.  
  16535. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/24/1998 13:27'!
  16536. browseChangeSet
  16537.     "Open a message list browser on the new and changed methods in the current change set"
  16538.  
  16539.     ChangedMessageSet openFor: myChangeSet
  16540.  
  16541. ! !
  16542.  
  16543. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/29/1998 08:20'!
  16544. changeSetMenu: aMenu
  16545.     "Could be for a single or double changeSorter"
  16546.     parent ifNotNil: [
  16547.     ^ aMenu labels: 
  16548. 'make changes go to me
  16549. new...
  16550. file into new...
  16551. show...
  16552. update
  16553. fileOut
  16554. browse
  16555. rename
  16556. copy all to other side
  16557. submerge into other side
  16558. subtract other side
  16559. edit preamble...
  16560. edit postscript...
  16561. clear
  16562. remove'
  16563.         lines: #(1 3 8 11 13 )
  16564.         selections: #(newCurrent newSet fileIntoNewChangeSet chooseCngSet update fileOut browseChangeSet rename copyAllToOther submergeIntoOtherSide subtractOtherSide editPreamble editPostscript clearChangeSet remove )]
  16565.  
  16566.     ifNil: ["Single ChangeSorter"
  16567.     ^ aMenu labels: 
  16568. 'make changes go to me
  16569. new...
  16570. file into new...
  16571. show...
  16572. update
  16573. fileOut
  16574. browse
  16575. rename
  16576. edit preamble...
  16577. edit postscript...
  16578. clear
  16579. remove'
  16580.         lines: #(1 3 8 10)
  16581.         selections: #(newCurrent newSet fileIntoNewChangeSet chooseCngSet update fileOut browseChangeSet rename editPreamble editPostscript clearChangeSet remove )]! !
  16582.  
  16583. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'jm 5/20/1998 12:15'!
  16584. changeSetMenuStart
  16585.  
  16586.     | menu |
  16587.     menu _ self changeSetMenu: CustomMenu new.
  16588.     menu ifNotNil: [menu invokeOn: self].
  16589. ! !
  16590.  
  16591. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 09:15'!
  16592. chooseCngSet
  16593.     "Put up a list of them"
  16594.     | index |
  16595.  
  16596.     self okToChange ifFalse: [^ self].
  16597.     ChangeSet instanceCount > AllChangeSets size ifTrue: [self class gatherChangeSets].
  16598.     index _ (PopUpMenu labels: 
  16599.         (AllChangeSets collect: [:each | each name]) asStringWithCr) startUp.
  16600.     index = 0 ifFalse: [self showChangeSet: (AllChangeSets at: index)].! !
  16601.  
  16602. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 09:06'!
  16603. clearChangeSet
  16604.     "Clear out the current change set, after getting a confirmation."
  16605.     | message |
  16606.  
  16607.     self okToChange ifFalse: [^ self].
  16608.     myChangeSet isEmpty ifFalse:
  16609.         [message _ 'Are you certain that you want to\forget all the changes in this set?' withCRs.
  16610.         (self confirm: message) ifFalse: [^ self]].
  16611.     myChangeSet clear.
  16612.     self changed: #classList.
  16613.     self changed: #messageList.
  16614.     self setContents.
  16615.     self changed: #contents.
  16616. ! !
  16617.  
  16618. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/29/1998 08:29'!
  16619. copyAllToOther
  16620.     "Copy this entire change set into the one on the other side"
  16621.     | other nextToView ii |
  16622.  
  16623.     other _ (parent other: self) myChangeSet.
  16624.     other assimilateAllChangesFoundIn: myChangeSet.
  16625.     (parent other: self) changed: #classList.    "Later the changeSet itself will notice..."
  16626.     (parent other: self) changed: #messageList.
  16627.  
  16628.     nextToView _ ((AllChangeSets includes: myChangeSet)
  16629.             and: [(ii _ AllChangeSets indexOf: myChangeSet) < AllChangeSets size])
  16630.         ifTrue: [AllChangeSets at: ii+1]
  16631.         ifFalse: [myChangeSet].
  16632.     self showChangeSet: nextToView! !
  16633.  
  16634. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 08:06'!
  16635. editPostscript
  16636.     "Allow the user to edit the receiver's change-set's postscript -- in a separate window"
  16637.  
  16638.     myChangeSet editPostscript! !
  16639.  
  16640. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 08:06'!
  16641. editPreamble
  16642.     "Allow the user to edit the receiver's change-set's preamble -- in a separate window."
  16643.  
  16644.     myChangeSet editPreamble! !
  16645.  
  16646. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 09:16'!
  16647. fileIntoNewChangeSet
  16648.     "Obtain a file designation from the user, and file its contents into a new change set whose name is a function of the filename.  Show the new set and leave the current changeSet unaltered."
  16649.     | aFileName  aNewChangeSet |
  16650.  
  16651.     self okToChange ifFalse: [^ self].
  16652.     aFileName _ FillInTheBlank request: 'Name of file to be imported: '.
  16653.     aFileName size == 0 ifTrue: [^ self].
  16654.     (FileDirectory default fileExists: aFileName) ifFalse:
  16655.         [^ self inform: 'Sorry -- cannot find that file'].
  16656.  
  16657.     aNewChangeSet _ self class 
  16658.             newChangesFromStream: (FileStream oldFileNamed: aFileName) 
  16659.             named: aFileName.
  16660.     aNewChangeSet ifNotNil: [self showChangeSet: aNewChangeSet]! !
  16661.  
  16662. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/24/1998 13:26'!
  16663. fileOut
  16664.     "File out the current change set."
  16665.  
  16666.     myChangeSet fileOut! !
  16667.  
  16668. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/24/1998 13:10'!
  16669. mainButtonName
  16670.  
  16671.     ^ myChangeSet name! !
  16672.  
  16673. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/24/1998 10:11'!
  16674. mainButtonState
  16675.     "The button activates the menu, but does not stay on"
  16676.     ^ false! !
  16677.  
  16678. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/30/1998 13:47'!
  16679. newCurrent
  16680.     "make my change set be the current one that changes go into"
  16681.     Smalltalk newChanges: myChangeSet.
  16682.     self changed: #relabel.! !
  16683.  
  16684. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 09:16'!
  16685. newSet
  16686.     "Create a new changeSet and show it.  make the new guy the current one.  Also, reject name if already in use."
  16687.     | newName newSet |
  16688.  
  16689.     self okToChange ifFalse: [^ self].
  16690.     newName _ FillInTheBlank request: 'A name for the new change set'
  16691.             initialAnswer: ChangeSet defaultName.
  16692.     newName isEmpty ifTrue: [^ self].
  16693.     (self class changeSetNamed: newName) ifNotNil:
  16694.             [^ self inform: 'Sorry that name is already used'].
  16695.  
  16696.     newSet _ ChangeSet new initialize name: newName.
  16697.     AllChangeSets add: newSet.
  16698.     self showChangeSet: newSet.
  16699.     self newCurrent.
  16700. ! !
  16701.  
  16702. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 09:07'!
  16703. remove
  16704.     "Completely destroy my change set.  Check if it's OK first"
  16705.  
  16706.     self okToChange ifFalse: [^ self].
  16707.     self removePrompting: true! !
  16708.  
  16709. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/24/1998 13:48'!
  16710. removePrompting: doPrompt
  16711.     "Completely destroy my change set.  Check if it's OK first,  and if doPrompt is true, get the user to confirm his intentions first"
  16712.     | message aName |
  16713.  
  16714.     aName _ myChangeSet name.
  16715.     myChangeSet okayToRemove ifFalse: [^ self]. "forms current changes for some project"
  16716.     (myChangeSet isEmpty or: [doPrompt not]) ifFalse:
  16717.         [message _ 'Are you certain that you want to 
  16718. remove (destroy) the change set
  16719. named  "', aName, '" ?'.
  16720.         (self confirm: message) ifFalse: [^ self]].
  16721.  
  16722.     "Go ahead and remove the change set"
  16723.     AllChangeSets remove: myChangeSet.
  16724.     myChangeSet wither.        "clear out its contents"
  16725.     self showChangeSet: Smalltalk changes.! !
  16726.  
  16727. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 08:38'!
  16728. rename
  16729.     "Store a new name string into the selected ChangeSet.  reject duplicate name; allow user to back out"
  16730.  
  16731.     | newName |
  16732.     newName _ FillInTheBlank request: 'New name for this change set'
  16733.                         initialAnswer: myChangeSet name.
  16734.     (newName = myChangeSet name or: [newName size == 0]) ifTrue:
  16735.             [^ self inform: 'No change made'].
  16736.  
  16737.     (self class changeSetNamed: newName) ifNotNil:
  16738.             [^ Utilities inform: 'Sorry that name is already used'].
  16739.  
  16740.     myChangeSet name: newName.
  16741.     self changed: #mainButtonName.
  16742.     self changed: #relabel.! !
  16743.  
  16744. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/29/1998 08:26'!
  16745. submergeIntoOtherSide
  16746.     "Copy the contents of the receiver to the other side, then remove the receiver -- all after checking that all is well."
  16747.     | other message nextToView i |
  16748.  
  16749.     self okToChange ifFalse: [^ self].
  16750.     other _ (parent other: self) changeSet.
  16751.     other == myChangeSet ifTrue: [^ self inform: 'Both sides are the same!!'].
  16752.     myChangeSet isEmpty ifTrue: [^ self inform: 'Nothing to copy.  To remove,
  16753. simply choose "remove".'].
  16754.  
  16755.     myChangeSet okayToRemove ifFalse: [^ self].
  16756.     message _ 'Please confirm:  copy all changes
  16757. in "', myChangeSet name, '" into "', other name, '"
  16758. and then destroy the change set
  16759. named "', myChangeSet name, '"?'.
  16760.  
  16761.     (self confirm: message) ifFalse: [^ self].
  16762.     other assimilateAllChangesFoundIn: myChangeSet.
  16763.  
  16764.     nextToView _ ((AllChangeSets includes: myChangeSet)
  16765.         and: [(i _ AllChangeSets indexOf: myChangeSet) < AllChangeSets size])
  16766.         ifTrue: [AllChangeSets at: i+1]
  16767.         ifFalse: [other].
  16768.  
  16769.     self removePrompting: false.
  16770.     self showChangeSet: nextToView.
  16771.     self class gatherChangeSets.
  16772.     (parent other: self) changed: #classList.
  16773.     (parent other: self) changed: #messageList.! !
  16774.  
  16775. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/29/1998 08:33'!
  16776. subtractOtherSide
  16777.     "Subtract the changes found on the other side from the requesting side."
  16778.  
  16779.     myChangeSet forgetAllChangesFoundIn: ((parent other: self) changeSet).
  16780.     self showChangeSet: myChangeSet! !
  16781.  
  16782. !ChangeSorter methodsFor: 'changeSet menu' stamp: 'tk 4/28/1998 20:58'!
  16783. update
  16784.     "recompute all of my panes"
  16785.  
  16786.     self okToChange ifFalse: [^ self].
  16787.     self showChangeSet: myChangeSet.
  16788.     parent ifNotNil: [
  16789.         (parent other: self) okToChange ifTrue: [
  16790.             (parent other: self) showChangeSet: 
  16791.                 (parent other: self) myChangeSet]].! !
  16792.  
  16793.  
  16794. !ChangeSorter methodsFor: 'class list' stamp: 'tk 5/7/1998 13:01'!
  16795. classList
  16796.     "Computed.  View should try to preserve selections, even though index changes"
  16797.  
  16798.     ^ myChangeSet changedClassNames
  16799. ! !
  16800.  
  16801. !ChangeSorter methodsFor: 'class list' stamp: 'tk 4/29/1998 09:57'!
  16802. classMenu: aMenu
  16803.     "Could be for a single or double changeSorter"
  16804.     parent ifNotNil: [
  16805.         ^ aMenu labels: 
  16806. 'copy to other side
  16807. delete from this change set
  16808. browse full
  16809. inst var refs...
  16810. inst var defs...
  16811. class var refs...
  16812. class vars'
  16813.         lines: #(2 3 )
  16814.         selections: #(copyClassToOther forgetClass browseMethodFull browseInstVarRefs browseInstVarDefs browseClassVarRefs browseClassVariables)]
  16815.  
  16816.     ifNil: [
  16817.         ^ aMenu labels: 
  16818. 'delete from this change set
  16819. browse full
  16820. inst var refs...
  16821. inst var defs...
  16822. class var refs...
  16823. class vars'
  16824.         lines: #(1 2 )
  16825.         selections: #(forgetClass browseMethodFull browseInstVarRefs browseInstVarDefs browseClassVarRefs browseClassVariables)]! !
  16826.  
  16827. !ChangeSorter methodsFor: 'class list' stamp: 'tk 5/7/1998 14:29'!
  16828. copyClassToOther
  16829.     "Place these changes in the other changeSet also"
  16830.     | other info cls |
  16831.  
  16832.     other _ (parent other: self) changeSet.
  16833.     (myChangeSet classRemoves includes: currentClassName) ifTrue: [
  16834.             ^ other noteRemovalOf: currentClassName].
  16835.  
  16836.     info _ myChangeSet classChangeAt: (cls _ self selectedClassOrMetaClass) name.
  16837.     info do: [:each | other atClass: cls add: each].
  16838.  
  16839.     info _ myChangeSet methodChanges at: cls name ifAbsent: [Dictionary new].
  16840.     info associationsDo: [:ass |
  16841.         other atSelector: ass key class: cls put: ass value].
  16842.     (parent other: self) showChangeSet: other.! !
  16843.  
  16844. !ChangeSorter methodsFor: 'class list' stamp: 'tk 4/24/1998 09:14'!
  16845. currentClassName
  16846.  
  16847.     ^ currentClassName! !
  16848.  
  16849. !ChangeSorter methodsFor: 'class list' stamp: 'tk 5/19/1998 12:41'!
  16850. currentClassName: aString
  16851.  
  16852.     currentClassName _ aString.
  16853.     currentSelector _ nil.    "fix by wod"
  16854.     self changed: #currentClassName.
  16855.     self changed: #messageList.
  16856.     self setContents.
  16857.     self changed: #contents.! !
  16858.  
  16859. !ChangeSorter methodsFor: 'class list' stamp: 'tk 5/20/1998 17:20'!
  16860. forgetClass
  16861.     "Remove all mention of this class from the changeSet"
  16862.  
  16863.     self okToChange ifFalse: [^ self].
  16864.     currentClassName ifNotNil: [
  16865.         myChangeSet removeClassChanges: self selectedClassOrMetaClass.
  16866.         currentClassName _ nil.
  16867.         currentSelector _ nil.
  16868.         self showChangeSet: myChangeSet].
  16869. ! !
  16870.  
  16871. !ChangeSorter methodsFor: 'class list' stamp: 'tk 4/24/1998 10:48'!
  16872. selectedClass
  16873.  
  16874.     ^ currentClassName ifNil: [nil]
  16875.         ifNotNil: [self selectedClassOrMetaClass theNonMetaClass]! !
  16876.  
  16877. !ChangeSorter methodsFor: 'class list' stamp: 'tk 5/7/1998 13:48'!
  16878. selectedClassOrMetaClass
  16879.     "Careful, the class may have been removed!!"
  16880.  
  16881.     | cName |
  16882.     currentClassName ifNil: [^ nil].
  16883.     (currentClassName endsWith: ' class')
  16884.         ifTrue: [cName _ (currentClassName copyFrom: 1 to: currentClassName size-6) asSymbol.
  16885.                 ^ (Smalltalk at: cName ifAbsent: [^nil]) class]
  16886.         ifFalse: [cName _ currentClassName asSymbol.
  16887.                 ^ Smalltalk at: cName ifAbsent: [nil]]! !
  16888.  
  16889.  
  16890. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/28/1998 18:49'!
  16891. browseVersions
  16892.     "Create and schedule a changelist browser on the versions of the 
  16893.     selected message."
  16894.     | class selector method category pair sourcePointer |
  16895.  
  16896.     (selector _ self selectedMessageName) ifNil: [^ self].
  16897.     class _ self selectedClassOrMetaClass.
  16898.     (class includesSelector: selector)
  16899.         ifTrue: [method _ class compiledMethodAt: selector.
  16900.                 category _ class whichCategoryIncludesSelector: selector.
  16901.                 sourcePointer _ nil]
  16902.         ifFalse: [pair _ myChangeSet methodRemoves
  16903.                             at: (Array with: class name with: selector)
  16904.                             ifAbsent: [^ nil].
  16905.                 sourcePointer _ pair first.
  16906.                 method _ CompiledMethod toReturnSelf setSourcePointer: sourcePointer.
  16907.                 category _ pair last].
  16908.     ChangeList
  16909.         browseVersionsOf: method
  16910.         class: self selectedClass meta: class isMeta
  16911.         category: category selector: selector
  16912.         lostMethodPointer: sourcePointer.
  16913. ! !
  16914.  
  16915. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/29/1998 10:08'!
  16916. copyMethodToOther
  16917.     "Place this change in the other changeSet also"
  16918.     | other info cls sel |
  16919.  
  16920.     currentSelector ifNotNil: [
  16921.         other _ (parent other: self) changeSet.
  16922.         cls _ self selectedClassOrMetaClass.
  16923.         sel _ currentSelector asSymbol.
  16924.  
  16925.         info _ myChangeSet methodChanges at: cls name ifAbsent: [Dictionary new].
  16926.         other atSelector: sel
  16927.             class: cls 
  16928.             put: (info at: sel).
  16929.         (parent other: self) showChangeSet: other]
  16930. ! !
  16931.  
  16932. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/24/1998 09:15'!
  16933. currentSelector
  16934.  
  16935.     ^ currentSelector! !
  16936.  
  16937. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/28/1998 20:48'!
  16938. currentSelector: messageName
  16939.  
  16940.     currentSelector _ messageName.
  16941.     self changed: #currentSelector.
  16942.     self setContents.
  16943.     self changed: #contents.! !
  16944.  
  16945. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/29/1998 10:11'!
  16946. forget
  16947.     "Drop this method from the changeSet"
  16948.  
  16949.     self okToChange ifFalse: [^ self].
  16950.     currentSelector ifNotNil: [
  16951.         myChangeSet removeSelectorChanges: self selectedMessageName 
  16952.             class: self selectedClassOrMetaClass.
  16953.         self showChangeSet: myChangeSet]! !
  16954.  
  16955. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/26/1998 22:34'!
  16956. messageList
  16957.  
  16958.     | probe |
  16959.     currentClassName ifNil: [^ #()].
  16960.     probe _ (currentClassName endsWith: ' class')
  16961.         ifTrue: [currentClassName]
  16962.         ifFalse: [currentClassName asSymbol].
  16963.     ^ ((myChangeSet selectorsInClass: probe) collect: 
  16964.                     [:each | each printString]) asSortedCollection
  16965. ! !
  16966.  
  16967. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/29/1998 10:03'!
  16968. messageMenu: aMenu shifted: shifted
  16969.     "Could be for a single or double changeSorter"
  16970.     shifted ifTrue: [^ self shiftedMessageMenu: aMenu].
  16971.     parent ifNotNil: [
  16972.         ^ aMenu labels: 
  16973. 'copy method to other side
  16974. delete method from change set
  16975. remove method from system
  16976. browse full
  16977. fileOut
  16978. printOut
  16979. senders of...
  16980. implementors of...
  16981. versions
  16982. more...'
  16983.         lines: #(1 3 6 9 )
  16984.         selections: #(copyMethodToOther forget removeMessage browseMethodFull fileOutMessage printOutMessage browseSendersOfMessages browseMessages browseVersions shiftedYellowButtonActivity )]
  16985.  
  16986.     ifNil: [^ aMenu labels: 
  16987. 'delete method from change set
  16988. remove method from system
  16989. browse full
  16990. fileOut
  16991. printOut
  16992. senders of...
  16993. implementors of...
  16994. versions
  16995. more...'
  16996.         lines: #(2 5 8 )
  16997.         selections: #( forget removeMessage browseMethodFull fileOutMessage printOutMessage browseSendersOfMessages browseMessages browseVersions shiftedYellowButtonActivity )]
  16998. ! !
  16999.  
  17000. !ChangeSorter methodsFor: 'message list' stamp: 'tk 5/18/1998 10:23'!
  17001. removeMessage
  17002.     "Remove the selected msg from the system.  Real work done by the parent, a ChangeSorter"
  17003.  
  17004.     | confirmation sel |
  17005.     self okToChange ifFalse: [^ self].
  17006.     currentSelector ifNotNil: [
  17007.         confirmation _ self selectedClassOrMetaClass 
  17008.             confirmRemovalOf: (sel _ self selectedMessageName).
  17009.         confirmation == 3 ifTrue: [^ self].
  17010.         myChangeSet removeSelectorChanges: sel 
  17011.             class: self selectedClassOrMetaClass.
  17012.         self selectedClassOrMetaClass removeSelector: sel.
  17013.         self update.
  17014.     "    self changed: #messageList.
  17015.         self setContents.
  17016.         self changed: #contents.
  17017.     "
  17018.         confirmation == 2 ifTrue:
  17019.             [Smalltalk browseAllCallsOn: sel]]! !
  17020.  
  17021. !ChangeSorter methodsFor: 'message list' stamp: 'jm 5/4/1998 07:32'!
  17022. selectedMessageName
  17023.  
  17024.     currentSelector ifNil: [^ nil].
  17025.     ^ currentSelector asSymbol! !
  17026.  
  17027. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/28/1998 19:02'!
  17028. shiftedMessageMenu: aMenu
  17029.  
  17030.     ^ aMenu labels: 'browse class hierarchy
  17031. browse class
  17032. browse method
  17033. implementors of sent messages
  17034. change sets with this method
  17035. inspect instances
  17036. inspect subinstances
  17037. more...' 
  17038.     lines: #(5 7 10)
  17039.     selections: #(classHierarchy browseClass 
  17040.         buildMessageBrowser browseAllMessages findMethodInChangeSets 
  17041.         inspectInstances inspectSubInstances
  17042.         unshiftedYellowButtonActivity)! !
  17043.  
  17044. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/28/1998 19:03'!
  17045. shiftedYellowButtonActivity
  17046.     "Invoke the model's other menu.  Just do what the controller would have done."
  17047.  
  17048.     | menu |
  17049.     menu _ self messageMenu: (CustomMenu new) shifted: true.
  17050.     menu == nil
  17051.         ifTrue: [Sensor waitNoButton]
  17052.         ifFalse: [menu invokeOn: self].
  17053. ! !
  17054.  
  17055. !ChangeSorter methodsFor: 'message list' stamp: 'tk 4/28/1998 19:16'!
  17056. unshiftedYellowButtonActivity
  17057.     "Invoke the model's other menu.  Just do what the controller would have done."
  17058.  
  17059.     | menu |
  17060.     menu _ self messageMenu: (CustomMenu new) shifted: false.
  17061.     menu == nil
  17062.         ifTrue: [Sensor waitNoButton]
  17063.         ifFalse: [menu invokeOn: self].
  17064. ! !
  17065.  
  17066.  
  17067. !ChangeSorter methodsFor: 'code pane' stamp: 'tk 5/18/1998 11:43'!
  17068. contents: aString notifying: aController 
  17069.     "Compile the code in aString. Notify aController of any syntax errors. 
  17070.     Create an error if the category of the selected message is unknown. 
  17071.     Answer false if the compilation fails. Otherwise, if the compilation 
  17072.     created a new method, deselect the current selection. Then answer true."
  17073.     | category selector class oldSelector |
  17074.  
  17075.     (class _ self selectedClassOrMetaClass) ifNil: [^ false].
  17076.     oldSelector _ self selectedMessageName.
  17077.     category _ class organization categoryOfElement: oldSelector.
  17078.     selector _ class compile: aString
  17079.                 classified: category
  17080.                 notifying: aController.
  17081.     selector ifNil: [^ false].
  17082.     (self messageList includes: selector)
  17083.         ifTrue: [self currentSelector: selector]
  17084.         ifFalse: [self currentSelector: oldSelector].
  17085.     self update.
  17086.     ^ true! !
  17087.  
  17088. !ChangeSorter methodsFor: 'code pane' stamp: 'tk 5/18/1998 14:40'!
  17089. setContents
  17090.     "return the source code that shows in the bottom pane"
  17091.     | sel class strm changeType |
  17092.     self clearUserEditFlag.
  17093.     currentClassName ifNil: [^ contents _ ''].
  17094.     class _ self selectedClassOrMetaClass.
  17095.     (sel _ currentSelector) == nil
  17096.         ifFalse: [changeType _ (myChangeSet atSelector: (sel _ sel asSymbol) class: class).
  17097.             changeType == #remove
  17098.                 ifTrue: [^ contents _ 'Method has been removed (see versions)'].
  17099.             changeType == #addedThenRemoved
  17100.                 ifTrue: [^ contents _ 'Added then removed (see versions)'].
  17101.             class ifNil: [^ contents _ 'Method was added, but cannot be found!!'].
  17102.             (class includesSelector: sel)
  17103.                 ifFalse: [^ contents _ 'Method was added, but cannot be found!!'].
  17104.             ^ contents _ (class sourceMethodAt: sel) copy]
  17105.         ifTrue: [strm _ WriteStream on: (String new: 100).
  17106.             (myChangeSet classChangeAt: currentClassName) do: [:each |
  17107.                 each = #remove ifTrue: [strm nextPutAll: 'Entire class was removed.'; cr].
  17108.                 each = #add ifTrue: [strm nextPutAll: 'Entire class was added.'; cr].
  17109.                 each = #change ifTrue: [strm nextPutAll: 'Class definition was changed.'; cr].
  17110.                 each = #comment ifTrue: [strm nextPutAll: 'New class comment.'; cr]].
  17111.             ^ contents _ strm contents].! !
  17112.  
  17113. !ChangeSorter methodsFor: 'code pane' stamp: 'di 5/22/1998 14:09'!
  17114. spawn: aString 
  17115.     "Create and schedule a message browser for the receiver in which the 
  17116.     argument, aString, contains characters to be edited in the text view."
  17117.  
  17118.     currentSelector ifNil: [^ self].
  17119.     ^ Browser
  17120.         openMessageBrowserForClass: self selectedClassOrMetaClass
  17121.         selector: self selectedMessageName
  17122.         editString: aString! !
  17123.  
  17124. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  17125.  
  17126. ChangeSorter class
  17127.     instanceVariableNames: ''!
  17128.  
  17129. !ChangeSorter class methodsFor: 'all' stamp: 'tk 5/1/1998 15:26'!
  17130. allChangeSetNames
  17131.     ^ self gatherChangeSets collect: [:c | c name]! !
  17132.  
  17133. !ChangeSorter class methodsFor: 'all' stamp: 'di 5/6/1998 16:40'!
  17134. browseChangeSetsWithClass: class selector: selector
  17135.     | hits index |
  17136.     hits _ self gatherChangeSets select: 
  17137.         [:cs | (cs atSelector: selector class: class) ~~ #none].
  17138.     hits isEmpty ifTrue: [^ PopUpMenu notify: class name,'.',selector , '
  17139. is not in any change set'].
  17140.     index _ hits size == 1
  17141.         ifTrue:    [1]
  17142.         ifFalse:    [(PopUpMenu labelArray: (hits collect: [:cs | cs name])
  17143.                     lines: #()) startUp].
  17144.     index = 0 ifTrue: [^ self].
  17145.     (ChangeSorter new myChangeSet: (hits at: index)) open.
  17146. ! !
  17147.  
  17148. !ChangeSorter class methodsFor: 'all' stamp: 'tk 4/24/1998 16:42'!
  17149. changeSetNamed: aName
  17150.     "Return the change set of the given name, or nil if none found.  1/22/96 sw"
  17151.  
  17152.     self gatherChangeSets.
  17153.     AllChangeSets do:
  17154.         [:aChangeSet | aChangeSet name = aName ifTrue:
  17155.             [^ aChangeSet]].
  17156.     ^ nil! !
  17157.  
  17158. !ChangeSorter class methodsFor: 'all' stamp: 'tk 4/24/1998 13:51'!
  17159. gatherChangeSets
  17160.     "Collect any change sets created in other projects"
  17161.  
  17162.     ChangeSet allInstancesDo: [:each |
  17163.         (AllChangeSets includes: each) ifFalse:
  17164.             [AllChangeSets add: each]].
  17165.     ^ AllChangeSets _ AllChangeSets select:
  17166.         [:each | each isMoribund not]
  17167.  
  17168.     "ChangeSorter gatherChangeSets"! !
  17169.  
  17170. !ChangeSorter class methodsFor: 'all' stamp: 'tk 5/1/1998 22:34'!
  17171. highestNumberedChangeSet
  17172.     "ChangeSorter highestNumberedChangeSet"
  17173.     ^ (self allChangeSetNames select: [:aString | aString startsWithDigit] thenCollect:
  17174.         [:aString | aString initialInteger]) max
  17175. ! !
  17176.  
  17177. !ChangeSorter class methodsFor: 'all' stamp: 'tk 4/24/1998 13:52'!
  17178. initialize
  17179.     AllChangeSets == nil ifTrue:
  17180.         [AllChangeSets _ OrderedCollection new].
  17181.     self gatherChangeSets.
  17182. ! !
  17183.  
  17184. !ChangeSorter class methodsFor: 'all' stamp: 'tk 4/24/1998 13:19'!
  17185. newChangesFromStream: aFileStream named: aFileName
  17186.     "File in the code from the file, into a new change set whose name is derived from the filename.  Leave the 'current change set' unchanged.   Returns the new change set;  Returns nil on failure."
  17187.  
  17188.     |  newName aNewChangeSet existingChanges |
  17189.  
  17190.     existingChanges _ Smalltalk changes.
  17191.     newName _ aFileName sansPeriodSuffix.
  17192.     (self changeSetNamed: newName) ~~ nil
  17193.         ifTrue:
  17194.             [self inform: 'Sorry -- "', newName, '" is already used as a change-set name'.
  17195.             aFileStream close.
  17196.             ^ nil].
  17197.  
  17198.     aNewChangeSet _ ChangeSet new initialize.
  17199.     aNewChangeSet name: newName.
  17200.     AllChangeSets add: aNewChangeSet.
  17201.     Smalltalk newChanges: aNewChangeSet.
  17202.     aFileStream fileIn.
  17203.     Transcript cr; show: 'File ', aFileName, ' successfully filed in to change set ', newName.
  17204.     Smalltalk newChanges: existingChanges.
  17205.     ^ aNewChangeSet! !
  17206.  
  17207. !ChangeSorter class methodsFor: 'all' stamp: 'jm 5/22/1998 11:33'!
  17208. removeChangeSetsBefore: stopName
  17209.     "Remove all change sets before the one with the given name."
  17210.     "ChangeSorter removeChangeSetsBefore: 'Beyond'" 
  17211.  
  17212.     | stop |
  17213.     (self confirm:
  17214. 'Really remove all change sets before
  17215. "', stopName, '"?')
  17216.         ifFalse: [^ self].
  17217.  
  17218.     self gatherChangeSets.
  17219.     stop _ false.
  17220.     ChangeSet allInstancesDo: [:changeSet |
  17221.         changeSet name = stopName ifTrue: [stop _ true].
  17222.         stop ifFalse: [
  17223.             changeSet okayToRemove ifTrue: [
  17224.                 AllChangeSets remove: changeSet ifAbsent: [].
  17225.                 changeSet wither]]].
  17226.     Smalltalk garbageCollect.
  17227.     AllChangeSets _ OrderedCollection new.
  17228.     self gatherChangeSets.
  17229. ! !
  17230.  
  17231. !ChangeSorter class methodsFor: 'all' stamp: 'di 5/12/1998 12:20'!
  17232. removeChangeSetsNamedSuchThat: nameBlock
  17233.     "ChangeSorter removeChangeSetsNamedSuchThat:
  17234.         [:name | name first isDigit and: [name initialInteger >= 275]]"
  17235.     self allChangeSetNames do:
  17236.         [:csName | (nameBlock value: csName) ifTrue: [AllChangeSets remove: (self changeSetNamed: csName) wither]]! !
  17237.  
  17238. !ChangeSorter class methodsFor: 'all' stamp: 'jm 5/20/1998 10:40'!
  17239. removeOldChangeSets
  17240.     "Ask the user to select a change set from a menu, then remove all change sets before the selected one."
  17241.     "ChangeSorter removeOldChangeSets" 
  17242.  
  17243.     | names stopName |
  17244.     self gatherChangeSets.
  17245.     names _ AllChangeSets collect: [:each | each name].
  17246.     stopName _ (SelectionMenu labelList: names selections: names) startUp.
  17247.     stopName ifNotNil: [self removeChangeSetsBefore: stopName].
  17248. ! !
  17249.  
  17250. !ChangeSorter class methodsFor: 'all' stamp: 'tk 4/30/1998 13:43'!
  17251. secondaryChangeSet
  17252.     "Answer a likely change set to use as the second initial one in a Dual Change Sorter.  "
  17253.     | last |
  17254.     self gatherChangeSets.
  17255.     AllChangeSets size == 1 ifTrue: [^ AllChangeSets first].
  17256.     ^ (last _ AllChangeSets last) == Smalltalk changes
  17257.         ifTrue:     [AllChangeSets at: (AllChangeSets size - 1)]
  17258.         ifFalse:    [last]! !
  17259. MessageSet subclass: #ChangedMessageSet
  17260.     instanceVariableNames: 'changeSet '
  17261.     classVariableNames: ''
  17262.     poolDictionaries: ''
  17263.     category: 'Interface-Browser'!
  17264.  
  17265. !ChangedMessageSet methodsFor: 'everything'!
  17266. changeSet: aChangeSet
  17267.     changeSet _ aChangeSet! !
  17268.  
  17269. !ChangedMessageSet methodsFor: 'everything' stamp: 'tk 4/26/1998 09:20'!
  17270. contents: aString notifying: aController
  17271.     | selectedMessageName selector oldMessageList cls |
  17272.     selectedMessageName _ self selectedMessageName.
  17273.     oldMessageList _ self messageList.
  17274.     contents _ nil.
  17275.     selector _ self selectedClassOrMetaClass
  17276.                 compile: aString
  17277.                 classified:  self selectedMessageCategoryName
  17278.                 notifying: aController.
  17279.     selector == nil ifTrue: [^ false].
  17280.     cls _ self selectedClassOrMetaClass.
  17281.     contents _ aString copy.
  17282.     selector ~~ selectedMessageName ifTrue: 
  17283.             [(oldMessageList includes: selector) ifFalse: [
  17284.                     self initializeMessageList: changeSet changedMessageListAugmented.
  17285.                     self changed: #messageList].
  17286.             self messageListIndex: (self messageList indexOf: (cls name, ' ', selector))].
  17287.     ^ true! !
  17288.  
  17289. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  17290.  
  17291. ChangedMessageSet class
  17292.     instanceVariableNames: ''!
  17293.  
  17294. !ChangedMessageSet class methodsFor: 'as yet unclassified' stamp: 'sw 3/9/97'!
  17295. openFor: aChangeSet
  17296.     "Open up a ChangedMessageSet browser on the given change set; this is a conventional message-list browser whose message list is the list of methods in aChangeSet.  After any method submission, the message list is refigured, making it plausibly dynamic.  "
  17297.     | messageSet |
  17298.  
  17299.     messageSet _ self messageList: aChangeSet changedMessageListAugmented.
  17300.     messageSet changeSet: aChangeSet.
  17301.     messageSet autoSelectString: nil.
  17302.     ScheduledControllers scheduleActive: 
  17303.                     (self open: messageSet name:  'Methods in Change Set ', aChangeSet name)! !
  17304. Object subclass: #CharRecog
  17305.     instanceVariableNames: 'mp p sts pts bmin bmax op cPat in dirs ftrs prevFeatures '
  17306.     classVariableNames: 'CharacterDictionary '
  17307.     poolDictionaries: 'TextConstants '
  17308.     category: 'System-Support'!
  17309. !CharRecog commentStamp: 'di 5/22/1998 16:32' prior: 0!
  17310. CharRecog comment:
  17311. 'Alan Kay''s "one-page" character recognizer.  Currently hooked up to text panes, such that you can get it started by hitting cmd-r in any pane.  
  17312.  
  17313. To reinitialize the recognition dictionary, evaluate
  17314.  
  17315.     CharRecog reinitializeCharacterDictionary
  17316.  
  17317.  '!
  17318.  
  17319.  
  17320. !CharRecog methodsFor: 'recognizer'!
  17321. directionFrom: p1 to: p2 | ex |
  17322.  
  17323. "This does 8 directions and is not used in current recognizer"
  17324. "get the bounding box"        ex _ p2 - p1. "unlike bmax-bmin, this can have negatives"
  17325.  
  17326. "Look for degenerate forms first: . - |"
  17327. "look for a dot"                ex abs < (3@3) ifTrue: [^' dot... '].
  17328. "look for hori line"            ((ex y = 0) or: [(ex x/ex y) abs > 2]) ifTrue:
  17329.     "look for w-e"                    [ex x > 0 ifTrue:[^' we-- ']
  17330.     "it's an e-w"                        ifFalse:[^' ew-- ']].
  17331. "look for vertical line"        ((ex x = 0) or: [(ex y/ex x) abs > 2]) ifTrue:
  17332.     "look for n-s"                [(ex y > 0) ifTrue:[ ^' ns||']
  17333.     "it's a s-n"                        ifFalse:[^' sn|| ']].
  17334. "look for a diagonal"            (ex x/ex y) abs <= 2 ifTrue:
  17335.     "se or ne"                    [ex x > 0 ifTrue:[ex y > 0 ifTrue:[^' se// ']. ^' ne// '].
  17336.     "sw or nw"                                    ex y > 0 ifTrue:[^' sw// ']. ^' nw// '].
  17337. ! !
  17338.  
  17339. !CharRecog methodsFor: 'recognizer'!
  17340. extractFeatures | xl xr yl yh reg px py |
  17341. "get extent bounding box"    in _ bmax - bmin. 
  17342.  
  17343. "Look for degenerate forms first: . - |"
  17344. "look for a dot"                in < (3@3) ifTrue: [^' dot... '].
  17345.  
  17346. "Feature 5: turns (these are already in ftrs)"
  17347.  
  17348. "Feature 4: absolute size"    in < (10@10) ifTrue: [ftrs _  'SML ', ftrs] ifFalse:
  17349.                             [in <=  (70@70) ifTrue: [ftrs _ 'REG ', ftrs] ifFalse:
  17350.                             [in > (70@70) ifTrue: [ftrs _ 'LRG ', ftrs]]].
  17351.  
  17352. "Feature 3: aspect ratio"
  17353.     "horizontal shape"        ((in y = 0) or: [(in x/in y) abs > 3]) ifTrue:
  17354.                                 [ftrs _ 'HOR ', ftrs] ifFalse:
  17355.     "vertical shape"            [((in x = 0) or: [(in y/in x) abs >= 3]) ifTrue:
  17356.                                 [ftrs _ 'VER ', ftrs] ifFalse:
  17357.     "boxy shape"            [((in x/in y) abs <= 3) ifTrue:
  17358.                                 [ftrs _ 'BOX ', ftrs.
  17359. "Now only for boxes"
  17360. "Feature 2: endstroke reg"    ftrs _ (self regionOf: (pts last)), ftrs.
  17361.                             
  17362. "Feature 1: startstroke reg"    ftrs _ (self regionOf: (pts contents at: 1)), ftrs.]]].
  17363.  
  17364. ^ftrs
  17365.  
  17366.  
  17367.  
  17368. ! !
  17369.  
  17370. !CharRecog methodsFor: 'recognizer'!
  17371. fourDirsFrom:  p1 to: p2 | ex |
  17372.  
  17373. "get the bounding box"        ex _ p2 - p1. "unlike bmax-bmin, this can have negatives"
  17374.  
  17375. "Look for degenerate forms first: . - |"
  17376. "look for a dot"                ex abs < (3@3) ifTrue: [^' dot... '].
  17377. "look for hori line"            ((ex y = 0) or: [(ex x/ex y) abs > 1]) ifTrue:
  17378.     "look for w-e"                    [ex x > 0 ifTrue:[^'WE ']
  17379.     "it's an e-w"                        ifFalse:[^'EW ']].
  17380. "look for vertical line"        ((ex x = 0) or: [(ex y/ex x) abs >= 1]) ifTrue:
  17381.     "look for n-s"                [(ex y > 0) ifTrue:[ ^'NS ']
  17382.     "it's a s-n"                        ifFalse:[^'SN ']].
  17383.  
  17384. "look for a diagonal            (ex x/ex y) abs <= 2 ifTrue:"
  17385.     "se or ne                    [ex x > 0 ifTrue:[ex y > 0 ifTrue:[^' se// ']. ^' ne// ']."
  17386.     "sw or nw                                    ex y > 0 ifTrue:[^' sw// ']. ^' nw// ']."
  17387. ! !
  17388.  
  17389. !CharRecog methodsFor: 'recognizer' stamp: 'jm 4/28/1998 05:37'!
  17390. learnPrev
  17391.     "The character recognized before this one was wrong.  (Got here via the gesture for 'wrong'.)  Bring up a dialog box on that char.  8/21/96 tk"
  17392.  
  17393.                         | old result |
  17394.     old _ CharacterDictionary at: prevFeatures ifAbsent: [^ ''].
  17395. "get right char from user"    result _ FillInTheBlank request:
  17396.                         ('Redefine the gesture we thought was "', old asString, '".', '
  17397. (Letter or:  tab  cr  wrong  bs  select  caret)
  17398. ', prevFeatures).
  17399.  
  17400. "ignore or..."                (result = '~' | result = '') ifTrue: ['']
  17401. "...enter new char"            ifFalse: [
  17402.                                 CharacterDictionary at: prevFeatures 
  17403.                                     put: result].
  17404.                     "caller erases bad char"
  17405. "good char"            ^ result! !
  17406.  
  17407. !CharRecog methodsFor: 'recognizer'!
  17408. recognize | prv cdir result features char r s t dir |
  17409.  
  17410. "Alan Kay's recognizer as of 1/31/96.  This version preserved for historical purposes, and also because it's still called by the not-yet-deployed method recogPar.  Within the current image, the recognizer is now called via #recognizeAndDispatch:until:"
  17411.  
  17412.  
  17413. "Inits"                (p _ Pen new) defaultNib: 1; down.
  17414.     "for points"        pts _ ReadWriteStream on: #().
  17415.  
  17416. "Event Loop"    
  17417.                     [(Sensor mousePoint x) < 50] whileFalse:
  17418.  
  17419. "First-Time"            [pts reset.        
  17420. "will hold features"        ftrs _ ''.
  17421.  
  17422.                       (Sensor anyButtonPressed) ifTrue:
  17423.                         [pts nextPut: (bmin _ bmax _ t _ s _ sts _ Sensor mousePoint).
  17424.                         p place: sts. cdir _ nil.
  17425.  
  17426. "Each-Time"        [Sensor anyButtonPressed] whileTrue:
  17427.                         [
  17428. "ink raw input"            p goto: (r _ Sensor mousePoint).
  17429. "smooth it"                s _ (0.5*s) + (0.5*r).
  17430. "thin the stream"        ((s x - t x) abs > 3 or:[(s y - t y) abs > 3]) ifTrue:
  17431.                             [ pts nextPut: t. 
  17432. "bounding box"            bmin _ bmin min: s. bmax _ bmax max: s.
  17433. "get current dir"                dir _ (self fourDirsFrom: t to: s). t _ s.
  17434.                             dir ~= ' dot... ' ifTrue: [
  17435. "store new dirs"                    cdir ~= dir ifTrue: [ftrs _ ftrs, (cdir _ dir)]].
  17436. "for inked t's"             p place: t; go: 1; place: r.
  17437.                             ].
  17438.  "End Each-Time Loop"    ].
  17439.  
  17440. "Last-Time"    
  17441.  
  17442. "save last points"        pts nextPut: t; nextPut: r.
  17443. "find rest of features"    features _ self extractFeatures.
  17444. "find char..."            char _ CharacterDictionary at: features ifAbsent:
  17445. "...or get from user"            [ result _ FillInTheBlank request:
  17446.                              'Not recognized. type char, or type ~: ', features.
  17447. "ignore or..."                result = '~' ifTrue: ['']
  17448. "...enter new char"            ifFalse: [CharacterDictionary at: features put: result. result]].
  17449.  
  17450. "control the editor"        (char = 'cr' ifTrue: [Transcript cr] ifFalse:
  17451.                         [char = 'bs' ifTrue: [Transcript bs] ifFalse:
  17452.                         [char = 'tab' ifTrue:[Transcript tab] ifFalse:
  17453.                         [Transcript show: char]]]). 
  17454.  
  17455. "End First-Time Loop"    ]. 
  17456.  
  17457. "End Event-Loop" ]. 
  17458.  
  17459.                
  17460.  ! !
  17461.  
  17462. !CharRecog methodsFor: 'recognizer'!
  17463. recognizeAndDispatch: charDispatchBlock ifUnrecognized: unrecognizedFeaturesBlock until: terminationBlock
  17464.     "Recognize characters, and dispatch each one found by evaluating charDispatchBlock; proceed until terminationBlock is true.  This method derives directly from Alan's 1/96 #recognize method, but factors out the character dispatch and the termination condition from the main body of the method.  2/2/96 sw.   2/5/96 sw: switch to using a class variable for the character dictionary, and don't put vacuous entries in the dictionary if the user gives an empty response to the prompt, and don't send empty characters onward, and use a variant of the FillInTheBlank that keeps the prompt clear of the working window.  8/17/96 tk: Turn cr, tab, bs into strings so they work.
  17465.      9/18/96 sw: in this variant, the block for handling unrecognized features is handed in as an argument, so that in some circumstances we can avoid putting up a prompt.  unrecognizedFeaturesBlock should be a one-argument block, which is handed in the features and which is expected to return a string which indicates the determined translation -- empty if none."
  17466.  
  17467.     | prv cdir features char r s t dir |
  17468.  
  17469. "Inits"                (p _ Pen new) defaultNib: 1; down.
  17470.     "for points"        pts _ ReadWriteStream on: #().
  17471.  
  17472. "Event Loop"    
  17473.                     [terminationBlock value] whileFalse:
  17474.  
  17475. "First-Time"            [pts reset.        
  17476. "will hold features"        ftrs _ ''.
  17477.  
  17478.                       (Sensor anyButtonPressed) ifTrue:
  17479.                         [pts nextPut: (bmin _ bmax _ t _ s _ sts _ Sensor mousePoint).
  17480.                         p place: sts. cdir _ nil.
  17481.  
  17482. "Each-Time"        [Sensor anyButtonPressed] whileTrue:
  17483. "ink raw input"            [p goto: (r _ Sensor mousePoint).
  17484. "smooth it"                s _ (0.5*s) + (0.5*r).
  17485. "thin the stream"        ((s x - t x) abs > 3 or:[(s y - t y) abs > 3]) ifTrue:
  17486.                             [pts nextPut: t. 
  17487. "bounding box"                bmin _ bmin min: s. bmax _ bmax max: s.
  17488. "get current dir"                dir _ (self fourDirsFrom: t to: s). t _ s.
  17489.                             dir ~= ' dot... ' ifTrue:
  17490. "store new dirs"                    [cdir ~= dir ifTrue: [ftrs _ ftrs, (cdir _ dir)]].
  17491. "for inked t's"                 p place: t; go: 1; place: r]].
  17492.  "End Each-Time Loop"
  17493.  
  17494. "Last-Time"    
  17495. "save last points"        pts nextPut: t; nextPut: r.
  17496. "find rest of features"    features _ self extractFeatures.
  17497. "find char..."            char _ CharacterDictionary at: features ifAbsent:
  17498.                             [unrecognizedFeaturesBlock value: features].
  17499.  
  17500. "special chars"        char size > 0 ifTrue:
  17501.                         [char = 'tab' ifTrue: [char _ Tab].
  17502.                         char = 'cr' ifTrue:    [char _ CR].
  17503. "must be a string"        char class == Character ifTrue: 
  17504.                             [char _ String with: char].
  17505.                         char = 'bs' ifTrue:    [char _ BS].
  17506. "control the editor"        charDispatchBlock value: char]]]
  17507.  ! !
  17508.  
  17509. !CharRecog methodsFor: 'recognizer'!
  17510. recognizeAndDispatch: charDispatchBlock until: terminationBlock
  17511.     "Recognize characters, and dispatch each one found by evaluating charDispatchBlock; proceed until terminationBlock is true. 9/18/96 sw"
  17512.  
  17513.     ^ self recognizeAndDispatch: charDispatchBlock
  17514.         ifUnrecognized: 
  17515.             [:features | self stringForUnrecognizedFeatures: features]
  17516.         until: terminationBlock
  17517.  ! !
  17518.  
  17519. !CharRecog methodsFor: 'recognizer'!
  17520. recognizeAndPutInTranscript
  17521.     "Call Alan's recognizer repeatedly until the mouse is near the left edge of the screen, and dispatch keystrokes inferred to the Trancript.  2/2/96 sw"
  17522.  
  17523.     ^ self recognizeAndDispatch:
  17524.  
  17525.         [:char | (char = 'cr') ifTrue: [Transcript cr] ifFalse:
  17526.                         [char = 'bs' ifTrue: [Transcript bs] ifFalse:
  17527.                         [char = 'tab' ifTrue:[Transcript tab] ifFalse:
  17528.                         [Transcript show: char]]]]
  17529.  
  17530.         until:
  17531.             [Sensor mousePoint x < 50]
  17532.  
  17533. "CharRecog new recognizeAndPutInTranscript"! !
  17534.  
  17535. !CharRecog methodsFor: 'recognizer'!
  17536. recogPar | prv cdir result features char r s t dir |
  17537.  
  17538. "Inits"                (p _ Pen new) defaultNib: 1; down.
  17539.     "for points"        pts _ ReadWriteStream on: #().
  17540.  
  17541. "Event Loop"    
  17542.         [Sensor anyButtonPressed] whileFalse: [(Sensor mousePoint x < 50) ifTrue: [^''].].
  17543.  
  17544. "First-Time"            pts reset.        
  17545. "will hold features"        ftrs _ ''.
  17546.  
  17547.                       (Sensor anyButtonPressed) ifTrue:
  17548.                         [pts nextPut: (bmin _ bmax _ t _ s _ sts _ Sensor mousePoint).
  17549.                         p place: sts. cdir _ nil.
  17550.  
  17551. "Each-Time"        [Sensor anyButtonPressed] whileTrue:
  17552.                         [
  17553. "ink raw input"            p goto: (r _ Sensor mousePoint).
  17554. "smooth it"                s _ (0.5*s) + (0.5*r).
  17555. "thin the stream"        ((s x - t x) abs > 3 or:[(s y - t y) abs > 3]) ifTrue:
  17556.                             [ pts nextPut: t. 
  17557. "bounding box"            bmin _ bmin min: s. bmax _ bmax max: s.
  17558. "get current dir"                dir _ (self fourDirsFrom: t to: s). t _ s.
  17559.                             dir ~= ' dot... ' ifTrue: [
  17560. "store new dirs"                    cdir ~= dir ifTrue: [ftrs _ ftrs, (cdir _ dir)]].
  17561. "for inked t's"             p place: t; go: 1; place: r.
  17562.                             ].
  17563.  "End Each-Time Loop"    ].
  17564.  
  17565. "Last-Time"    
  17566. "start a new recog for next point"    [CharRecog new recognize] fork.
  17567.  
  17568. "save last points"        pts nextPut: t; nextPut: r.
  17569. "find rest of features"    features _ self extractFeatures.
  17570. "find char..."            char _ CharacterDictionary at: features ifAbsent:
  17571. "...or get from user"            [ result _ FillInTheBlank request:
  17572.                              'Not recognized. type char, or type ~: ', features.
  17573. "ignore or..."                result = '~' ifTrue: ['']
  17574. "...enter new char"            ifFalse: [CharacterDictionary at: features put: result. result]].
  17575.  
  17576. "control the editor"        (char = 'cr' ifTrue: [Transcript cr] ifFalse:
  17577.                         [char = 'bs' ifTrue: [Transcript bs] ifFalse:
  17578.                         [char = 'tab' ifTrue:[Transcript tab] ifFalse:
  17579.                         [Transcript show: char]]]). 
  17580.  
  17581. "End First-Time Loop"    ]. 
  17582.  
  17583.  
  17584.  
  17585.                
  17586.  ! !
  17587.  
  17588. !CharRecog methodsFor: 'recognizer'!
  17589. regionOf: pt 
  17590.  
  17591. | px py reg xl yl yh xr rg |
  17592. "it's some other character"    rg _ in/3.     xl _ bmin x + rg x. xr _ bmax x - rg x.
  17593. "divide box into 9 regions"                yl _ bmin y + rg y. yh _ bmax y - rg y.
  17594.  
  17595.                     px _ pt x. py _ pt y.
  17596.                     reg _ (px < xl ifTrue: [py < yl ifTrue: ['NW ']
  17597.                                         "py >= yl"    ifFalse:[ py < yh ifTrue:['W ']
  17598.                                                                     ifFalse: ['SW ']]]
  17599.                     ifFalse: [px < xr ifTrue: [py < yl ifTrue: ['N ']
  17600.                                                     ifFalse: [py < yh ifTrue: ['C ']
  17601.                                                                     ifFalse: ['S ']]]
  17602.                     ifFalse: [py < yl ifTrue: ['NE ']
  17603.                                     ifFalse: [py < yh ifTrue: ['E ']
  17604.                                                     ifFalse: ['SE ']]]]).
  17605. ^reg.
  17606.                     ! !
  17607.  
  17608. !CharRecog methodsFor: 'recognizer' stamp: 'jm 4/28/1998 05:37'!
  17609. stringForUnrecognizedFeatures: features
  17610.     "Prompt the user for what string the current features represent, and return the result.  9/18/96 sw"
  17611.  
  17612.     | result |
  17613.     result _ FillInTheBlank request:
  17614. ('Not recognized. type char, or "tab", "cr" or "bs",
  17615. or hit return to ignore 
  17616. ', features).
  17617.  
  17618.     ^ (result = '~' | result = '')
  17619.         ifTrue:
  17620.             ['']
  17621.         ifFalse:
  17622.             [CharacterDictionary at: features put: result. result]! !
  17623.  
  17624. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  17625.  
  17626. CharRecog class
  17627.     instanceVariableNames: ''!
  17628.  
  17629. !CharRecog class methodsFor: 'initialization'!
  17630. initialize
  17631.     "Iniitialize the character dictionary if it doesn't exist yet.  2/5/96 sw"
  17632.  
  17633.     CharacterDictionary == nil ifTrue:
  17634.         [CharacterDictionary _ Dictionary new]! !
  17635.  
  17636. !CharRecog class methodsFor: 'initialization'!
  17637. reinitializeCharacterDictionary
  17638.     "Reset the character dictionary to be empty, ready for a fresh start.  2/5/96 sw"
  17639.  
  17640.     CharacterDictionary _ Dictionary new
  17641.  
  17642. "CharRecog reinitializeCharacterDictionary" ! !
  17643.  
  17644.  
  17645. !CharRecog class methodsFor: 'saving dictionary'!
  17646. readRecognizerDictionaryFrom: aFileName
  17647.     "Read a fresh version of the Recognizer dictionary in from a file of the given name.  7/26/96 sw"
  17648.     "CharRecog readRecognizerDictionaryFrom: 'RecogDictionary.2 fixed'"
  17649.  
  17650.    | aReferenceStream |
  17651.    aReferenceStream _ ReferenceStream fileNamed: aFileName.
  17652.    CharacterDictionary _ aReferenceStream next.
  17653.    aReferenceStream close.
  17654. ! !
  17655.  
  17656. !CharRecog class methodsFor: 'saving dictionary'!
  17657. saveRecognizerDictionaryTo: aFileName
  17658.     "Save the current state of the Recognizer dictionary to disk.  7/26/96 sw"
  17659.  
  17660.    | aReferenceStream |
  17661. aReferenceStream _ ReferenceStream fileNamed: aFileName.
  17662.    aReferenceStream nextPut: CharacterDictionary.
  17663.    aReferenceStream close! !
  17664. Magnitude subclass: #Character
  17665.     instanceVariableNames: 'value '
  17666.     classVariableNames: 'CharacterTable '
  17667.     poolDictionaries: ''
  17668.     category: 'Collections-Text'!
  17669. !Character commentStamp: 'di 5/22/1998 16:32' prior: 0!
  17670. Character comment:
  17671. 'I represent a character by storing its associated ASCII code (extended to 256 codes). My instances are created uniquely, so that all instances of a character ($R, for example) are identical.'!
  17672.  
  17673.  
  17674. !Character methodsFor: 'accessing'!
  17675. asciiValue
  17676.     "Answer the value of the receiver that represents its ascii encoding."
  17677.  
  17678.     ^value! !
  17679.  
  17680. !Character methodsFor: 'accessing'!
  17681. digitValue
  17682.     "Answer 0-9 if the receiver is $0-$9, 10-35 if it is $A-$Z, and < 0 
  17683.     otherwise. This is used to parse literal numbers of radix 2-36."
  17684.  
  17685.     value <= $9 asciiValue 
  17686.         ifTrue: [^value - $0 asciiValue].
  17687.     value >= $A asciiValue 
  17688.         ifTrue: [value <= $Z asciiValue ifTrue: [^value - $A asciiValue + 10]].
  17689.     ^ -1! !
  17690.  
  17691.  
  17692. !Character methodsFor: 'comparing'!
  17693. < aCharacter 
  17694.     "Answer true if the receiver's value < aCharacter's value."
  17695.  
  17696.     ^self asciiValue < aCharacter asciiValue! !
  17697.  
  17698. !Character methodsFor: 'comparing'!
  17699. = aCharacter 
  17700.     "Primitive. Answer true if the receiver and the argument are the same
  17701.     object (have the same object pointer) and false otherwise. Optional. See
  17702.     Object documentation whatIsAPrimitive."
  17703.  
  17704.     <primitive: 110>
  17705.     ^self == aCharacter! !
  17706.  
  17707. !Character methodsFor: 'comparing'!
  17708. > aCharacter 
  17709.     "Answer true if the receiver's value > aCharacter's value."
  17710.  
  17711.     ^self asciiValue > aCharacter asciiValue! !
  17712.  
  17713. !Character methodsFor: 'comparing'!
  17714. hash
  17715.     "Hash is reimplemented because = is implemented."
  17716.  
  17717.     ^value! !
  17718.  
  17719.  
  17720. !Character methodsFor: 'testing'!
  17721. isAlphaNumeric
  17722.     "Answer whether the receiver is a letter or a digit."
  17723.  
  17724.     ^self isLetter or: [self isDigit]! !
  17725.  
  17726. !Character methodsFor: 'testing'!
  17727. isDigit
  17728.     "Answer whether the receiver is a digit."
  17729.  
  17730.     ^value >= 48 and: [value <= 57]! !
  17731.  
  17732. !Character methodsFor: 'testing'!
  17733. isLetter
  17734.     "Answer whether the receiver is a letter."
  17735.  
  17736.     ^(8r141 <= value and: [value <= 8r172])
  17737.         or: [8r101 <= value and: [value <= 8r132]]! !
  17738.  
  17739. !Character methodsFor: 'testing'!
  17740. isLowercase
  17741.     "Answer whether the receiver is a lowercase letter.
  17742.     (The old implementation answered whether the receiver is not an uppercase letter.)"
  17743.  
  17744.     ^8r141 <= value and: [value <= 8r172]! !
  17745.  
  17746. !Character methodsFor: 'testing'!
  17747. isSeparator
  17748.     "Answer whether the receiver is one of the separator characters--space, 
  17749.     cr, tab, line feed, or form feed."
  17750.  
  17751.     value = 32 ifTrue: [^true].    "space"
  17752.     value = 13 ifTrue: [^true].    "cr"
  17753.     value = 9 ifTrue: [^true].    "tab"
  17754.     value = 10 ifTrue: [^true].    "line feed"
  17755.     value = 12 ifTrue: [^true].    "form feed"
  17756.     ^false! !
  17757.  
  17758. !Character methodsFor: 'testing'!
  17759. isSpecial
  17760.     "Answer whether the receiver is one of the special characters"
  17761.  
  17762.     ^'+/\*~<>=@%|&?!!' includes: self! !
  17763.  
  17764. !Character methodsFor: 'testing'!
  17765. isUppercase
  17766.     "Answer whether the receiver is an uppercase letter.
  17767.     (The old implementation answered whether the receiver is not a lowercase letter.)"
  17768.  
  17769.     ^8r101 <= value and: [value <= 8r132]! !
  17770.  
  17771. !Character methodsFor: 'testing'!
  17772. isVowel
  17773.     "Answer whether the receiver is one of the vowels, AEIOU, in upper or 
  17774.     lower case."
  17775.  
  17776.     ^'AEIOU' includes: self asUppercase! !
  17777.  
  17778. !Character methodsFor: 'testing'!
  17779. tokenish
  17780.     "Answer whether the receiver is a valid token-character--letter, digit, or 
  17781.     colon."
  17782.  
  17783.     ^self isLetter or: [self isDigit or: [self = $:]]! !
  17784.  
  17785.  
  17786. !Character methodsFor: 'copying'!
  17787. copy
  17788.     "Answer with the receiver because Characters are unique."! !
  17789.  
  17790. !Character methodsFor: 'copying'!
  17791. deepCopy
  17792.     "Answer with the receiver because Characters are unique."! !
  17793.  
  17794.  
  17795. !Character methodsFor: 'printing'!
  17796. hex
  17797.     ^ String with: ('0123456789ABCDEF' at: value//16+1)
  17798.             with:  ('0123456789ABCDEF' at: value\\16+1)! !
  17799.  
  17800. !Character methodsFor: 'printing'!
  17801. isLiteral
  17802.  
  17803.     ^true! !
  17804.  
  17805. !Character methodsFor: 'printing'!
  17806. printOn: aStream
  17807.  
  17808.     aStream nextPut: $$.
  17809.     aStream nextPut: self! !
  17810.  
  17811. !Character methodsFor: 'printing'!
  17812. storeOn: aStream
  17813.     "Character literals are preceded by '$'."
  17814.  
  17815.     aStream nextPut: $$; nextPut: self! !
  17816.  
  17817.  
  17818. !Character methodsFor: 'converting'!
  17819. asCharacter
  17820.     "Answer the receiver itself."
  17821.  
  17822.     ^self! !
  17823.  
  17824. !Character methodsFor: 'converting'!
  17825. asInteger
  17826.     "Answer the value of the receiver."
  17827.  
  17828.     ^value! !
  17829.  
  17830. !Character methodsFor: 'converting'!
  17831. asLowercase
  17832.     "If the receiver is uppercase, answer its matching lowercase Character."
  17833.     
  17834.     (8r101 <= value and: [value <= 8r132])  "self isUppercase"
  17835.         ifTrue: [^ Character value: value + 8r40]
  17836.         ifFalse: [^ self]! !
  17837.  
  17838. !Character methodsFor: 'converting'!
  17839. asString
  17840.     | cString |
  17841.     cString _ String new: 1.
  17842.     cString at: 1 put: self.
  17843.     ^ cString! !
  17844.  
  17845. !Character methodsFor: 'converting'!
  17846. asSymbol 
  17847.     "Answer a Symbol consisting of the receiver as the only element."
  17848.  
  17849.     ^Symbol internCharacter: self! !
  17850.  
  17851. !Character methodsFor: 'converting'!
  17852. asUppercase
  17853.     "If the receiver is lowercase, answer its matching uppercase Character."
  17854.     
  17855.     (8r141 <= value and: [value <= 8r172])  "self isLowercase"
  17856.         ifTrue: [^ Character value: value - 8r40]
  17857.         ifFalse: [^ self]! !
  17858.  
  17859. !Character methodsFor: 'converting'!
  17860. to: other
  17861.     "Answer with a collection in ascii order -- $a to: $z"
  17862.     ^ (self asciiValue to: other asciiValue) collect:
  17863.                 [:ascii | Character value: ascii]! !
  17864.  
  17865. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  17866.  
  17867. Character class
  17868.     instanceVariableNames: ''!
  17869.  
  17870. !Character class methodsFor: 'class initialization'!
  17871. initialize
  17872.     "Create the table of unique Characters. This code is not shown so that the
  17873.     user can not destroy the system by trying to recreate the table."! !
  17874.  
  17875.  
  17876. !Character class methodsFor: 'instance creation'!
  17877. digitValue: x 
  17878.     "Answer the Character whose digit value is x. For example, answer $9 for 
  17879.     x=9, $0 for x=0, $A for x=10, $Z for x=35."
  17880.  
  17881.     | index |
  17882.     index _ x asInteger.
  17883.     ^CharacterTable at: 
  17884.         (index < 10
  17885.             ifTrue: [48 + index]
  17886.             ifFalse: [55 + index])
  17887.         + 1! !
  17888.  
  17889. !Character class methodsFor: 'instance creation'!
  17890. new
  17891.     "Creating new characters is not allowed."
  17892.  
  17893.     self error: 'cannot create new characters'! !
  17894.  
  17895. !Character class methodsFor: 'instance creation'!
  17896. separators
  17897.     ^ #(32 "space"
  17898.         13 "cr"
  17899.         9 "tab"
  17900.         10 "line feed"
  17901.         12 "form feed")
  17902.         collect: [:v | Character value: v]
  17903.  
  17904.     
  17905. ! !
  17906.  
  17907. !Character class methodsFor: 'instance creation'!
  17908. value: anInteger 
  17909.     "Answer the Character whose value is anInteger."
  17910.  
  17911.     ^CharacterTable at: anInteger + 1! !
  17912.  
  17913.  
  17914. !Character class methodsFor: 'accessing untypeable characters'!
  17915. backspace
  17916.     "Answer the Character representing a backspace."
  17917.  
  17918.     ^self value: 8! !
  17919.  
  17920. !Character class methodsFor: 'accessing untypeable characters'!
  17921. cr
  17922.     "Answer the Character representing a carriage return."
  17923.  
  17924.     ^self value: 13! !
  17925.  
  17926. !Character class methodsFor: 'accessing untypeable characters'!
  17927. enter
  17928.     "Answer the Character representing enter."
  17929.  
  17930.     ^self value: 3! !
  17931.  
  17932. !Character class methodsFor: 'accessing untypeable characters'!
  17933. linefeed
  17934.     "Answer the Character representing a linefeed."
  17935.  
  17936.     ^self value: 10! !
  17937.  
  17938. !Character class methodsFor: 'accessing untypeable characters'!
  17939. newPage
  17940.     "Answer the Character representing a form feed."
  17941.  
  17942.     ^self value: 12! !
  17943.  
  17944. !Character class methodsFor: 'accessing untypeable characters'!
  17945. space
  17946.     "Answer the Character representing a space."
  17947.  
  17948.     ^self value: 32! !
  17949.  
  17950. !Character class methodsFor: 'accessing untypeable characters'!
  17951. tab
  17952.     "Answer the Character representing a tab."
  17953.  
  17954.     ^self value: 9! !
  17955.  
  17956.  
  17957. !Character class methodsFor: 'constants' stamp: 'tk 12/11/97 09:29'!
  17958. alphabet
  17959.     ^ 'abdcefghijklmnopqrstuvwxyz'! !
  17960.  
  17961. !Character class methodsFor: 'constants'!
  17962. characterTable
  17963.     "Answer the class variable in which unique Characters are stored."
  17964.  
  17965.     ^CharacterTable! !
  17966. Rectangle subclass: #CharacterBlock
  17967.     instanceVariableNames: 'stringIndex text textLine '
  17968.     classVariableNames: ''
  17969.     poolDictionaries: 'TextConstants '
  17970.     category: 'Graphics-Support'!
  17971. !CharacterBlock commentStamp: 'di 5/22/1998 16:32' prior: 0!
  17972. CharacterBlock comment:
  17973. 'My instances contain information about displayed characters. They are used to return the results of methods:
  17974.     Paragraph characterBlockAtPoint: aPoint and
  17975.     Paragraph characterBlockForIndex: stringIndex.
  17976. Any recomposition or movement of a Paragraph can make the instance obsolete.'!
  17977.  
  17978.  
  17979. !CharacterBlock methodsFor: 'accessing'!
  17980. stringIndex
  17981.     "Answer the position of the receiver in the string it indexes."
  17982.  
  17983.     ^stringIndex! !
  17984.  
  17985. !CharacterBlock methodsFor: 'accessing' stamp: 'di 12/2/97 14:33'!
  17986. textLine
  17987.     ^ textLine! !
  17988.  
  17989. !CharacterBlock methodsFor: 'accessing' stamp: 'di 12/2/97 14:33'!
  17990. textLine: aLine
  17991.     textLine _ aLine! !
  17992.  
  17993.  
  17994. !CharacterBlock methodsFor: 'comparing'!
  17995. < aCharacterBlock 
  17996.     "Answer whether the string index of the receiver precedes that of 
  17997.     aCharacterBlock."
  17998.  
  17999.     ^stringIndex < aCharacterBlock stringIndex! !
  18000.  
  18001. !CharacterBlock methodsFor: 'comparing'!
  18002. <= aCharacterBlock 
  18003.     "Answer whether the string index of the receiver does not come after that 
  18004.     of aCharacterBlock."
  18005.  
  18006.     ^(self > aCharacterBlock) not! !
  18007.  
  18008. !CharacterBlock methodsFor: 'comparing'!
  18009. = aCharacterBlock
  18010.  
  18011.     self species = aCharacterBlock species
  18012.         ifTrue: [^stringIndex = aCharacterBlock stringIndex]
  18013.         ifFalse: [^false]! !
  18014.  
  18015. !CharacterBlock methodsFor: 'comparing'!
  18016. > aCharacterBlock 
  18017.     "Answer whether the string index of the receiver comes after that of 
  18018.     aCharacterBlock."
  18019.  
  18020.     ^aCharacterBlock < self! !
  18021.  
  18022. !CharacterBlock methodsFor: 'comparing'!
  18023. >= aCharacterBlock 
  18024.     "Answer whether the string index of the receiver does not precede that of 
  18025.     aCharacterBlock."
  18026.  
  18027.     ^(self < aCharacterBlock) not! !
  18028.  
  18029.  
  18030. !CharacterBlock methodsFor: 'printing' stamp: 'di 12/2/97 19:15'!
  18031. printOn: aStream
  18032.  
  18033.     aStream nextPutAll: 'a CharacterBlock with index '.
  18034.     stringIndex printOn: aStream.
  18035.     (text ~~ nil and: [text size> 0 and: [stringIndex between: 1 and: text size]])
  18036.         ifTrue: [aStream nextPutAll: ' and character '.
  18037.                 (text at: stringIndex) printOn: aStream].
  18038.     aStream nextPutAll: ' and rectangle '.
  18039.     super printOn: aStream.
  18040.     textLine ifNotNil: [aStream cr; nextPutAll: ' in '.
  18041.                 textLine printOn: aStream].
  18042. ! !
  18043.  
  18044.  
  18045. !CharacterBlock methodsFor: 'private'!
  18046. moveBy: aPoint 
  18047.     "Change the corner positions of the receiver so that its area translates by 
  18048.     the amount defined by the argument, aPoint."
  18049.  
  18050.     origin _ origin + aPoint.
  18051.     corner _ corner + aPoint! !
  18052.  
  18053. !CharacterBlock methodsFor: 'private' stamp: 'di 10/23/97 22:33'!
  18054. stringIndex: anInteger text: aText topLeft: topLeft extent: extent
  18055.  
  18056.     stringIndex _ anInteger.
  18057.     text _ aText.
  18058.     super setOrigin: topLeft corner: topLeft + extent ! !
  18059. CharacterScanner subclass: #CharacterBlockScanner
  18060.     instanceVariableNames: 'characterPoint characterIndex lastCharacter lastCharacterExtent lastSpaceOrTabExtent nextLeftMargin specialWidth '
  18061.     classVariableNames: ''
  18062.     poolDictionaries: 'TextConstants '
  18063.     category: 'Graphics-Support'!
  18064. !CharacterBlockScanner commentStamp: 'di 5/22/1998 16:32' prior: 0!
  18065. CharacterBlockScanner comment:
  18066. 'My instances are used to scan text to compute the CharacterBlock for a character specified by its index in the text or its proximity to the cursor location.'!
  18067.  
  18068.  
  18069. !CharacterBlockScanner methodsFor: 'scanning'!
  18070. characterBlockAtPoint: aPoint in: aParagraph
  18071.     "Answer a CharacterBlock for character in aParagraph at point aPoint. It 
  18072.     is assumed that aPoint has been transformed into coordinates appropriate 
  18073.     to the text's destination form rectangle and the composition rectangle."
  18074.  
  18075.     super initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle.
  18076.     characterPoint _ aPoint.
  18077.     ^self buildCharacterBlockIn: aParagraph! !
  18078.  
  18079. !CharacterBlockScanner methodsFor: 'scanning' stamp: 'di 12/2/97 14:30'!
  18080. characterBlockAtPoint: aPoint index: index in: textLine
  18081.     | runLength lineStop done stopCondition |
  18082.     line _ textLine.
  18083.     characterIndex _ index.  " == nil means scanning for point"
  18084.     characterPoint _ aPoint.
  18085.     (characterPoint == nil or: [characterPoint y > line bottom])
  18086.         ifTrue: [characterPoint _ line bottomRight].
  18087.     (text isEmpty or: [(characterPoint y < line top or: [characterPoint x < line left])
  18088.                 or: [characterIndex ~~ nil and: [characterIndex < line first]]])
  18089.         ifTrue:    [^ (CharacterBlock new stringIndex: line first text: text
  18090.                     topLeft: line leftMargin@line top extent: 0 @ textStyle lineGrid)
  18091.                     textLine: line].
  18092.     rightMargin _ line rightMargin.
  18093.     destX _ leftMargin _ line leftMarginForAlignment: textStyle alignment.
  18094.     destY _ line top.
  18095.     lastIndex _ line first.
  18096.     self setStopConditions.        "also sets font"
  18097.     runLength _ text runLengthFor: line first.
  18098.     characterIndex ~~ nil
  18099.         ifTrue:    [lineStop _ characterIndex  "scanning for index"]
  18100.         ifFalse:    [lineStop _ line last  "scanning for point"].
  18101.     runStopIndex _ lastIndex + (runLength - 1) min: lineStop.
  18102.     lastCharacterExtent _ 0 @ line lineHeight.
  18103.     spaceCount _ 0.
  18104.  
  18105.     done  _ false.
  18106.     [done] whileFalse:
  18107.         [stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex
  18108.             in: text string rightX: characterPoint x
  18109.             stopConditions: stopConditions kern: kern displaying: false.
  18110.         "see setStopConditions for stopping conditions for character block     operations."
  18111.         self lastCharacterExtentSetX: (specialWidth == nil
  18112.             ifTrue: [font widthOf: (text at: lastIndex)]
  18113.             ifFalse: [specialWidth]).
  18114.         (self perform: stopCondition) ifTrue:
  18115.             [^ (CharacterBlock new
  18116.                 stringIndex: (characterIndex==nil ifTrue: [lastIndex] ifFalse: [characterIndex])
  18117.                 text: text topLeft: characterPoint extent: lastCharacterExtent)
  18118.                 textLine: line]]! !
  18119.  
  18120. !CharacterBlockScanner methodsFor: 'scanning'!
  18121. characterBlockForIndex: targetIndex in: aParagraph 
  18122.     "Answer a CharacterBlock for character in aParagraph at targetIndex. The 
  18123.     coordinates in the CharacterBlock will be appropriate to the intersection 
  18124.     of the destination form rectangle and the composition rectangle."
  18125.  
  18126.     super 
  18127.         initializeFromParagraph: aParagraph 
  18128.         clippedBy: aParagraph clippingRectangle.
  18129.     characterIndex _ targetIndex.
  18130.     characterPoint _ 
  18131.         aParagraph rightMarginForDisplay @ 
  18132.             (aParagraph topAtLineIndex: 
  18133.                 (aParagraph lineIndexOfCharacterIndex: characterIndex)).
  18134.     ^self buildCharacterBlockIn: aParagraph! !
  18135.  
  18136. !CharacterBlockScanner methodsFor: 'scanning'!
  18137. characterNotInFont 
  18138.     "This does not handle character selection nicely, i.e., illegal characters are a 
  18139.     little tricky to select.  Since the end of a run or line is subverted here by actually
  18140.     having the scanner scan a different string in order to manage the illegal 
  18141.     character, things are not in an absolutely correct state for the character 
  18142.     location code.  If this becomes too odious in use, logic will be added to accurately 
  18143.     manage the situation."
  18144.  
  18145.     lastCharacterExtent _ 
  18146.         (font widthOf: (font maxAscii + 1) asCharacter) @ line lineHeight.
  18147.     ^super characterNotInFont! !
  18148.  
  18149. !CharacterBlockScanner methodsFor: 'scanning' stamp: 'di 11/12/97 19:34'!
  18150. placeEmbeddedObject: anchoredMorph
  18151.     (super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false].
  18152.     specialWidth _ width.
  18153.     ^ true! !
  18154.  
  18155.  
  18156. !CharacterBlockScanner methodsFor: 'stop conditions'!
  18157. cr 
  18158.     "Answer a CharacterBlock that specifies the current location of the mouse 
  18159.     relative to a carriage return stop condition that has just been 
  18160.     encountered. The ParagraphEditor convention is to denote selections by 
  18161.     CharacterBlocks, sometimes including the carriage return (cursor is at 
  18162.     the end) and sometimes not (cursor is in the middle of the text)."
  18163.  
  18164.     ((characterIndex ~= nil
  18165.         and: [characterIndex > text size])
  18166.             or: [(line last = text size)
  18167.                 and: [(destY + line lineHeight) < characterPoint y]])
  18168.         ifTrue:    ["When off end of string, give data for next character"
  18169.                 destY _ destY +  line lineHeight.
  18170.                 lastCharacter _ nil.
  18171.                 characterPoint _ ((text at: lastIndex) = CR
  18172.                                 ifTrue: [leftMargin]
  18173.                                 ifFalse: [nextLeftMargin]) @ destY.
  18174.                 lastIndex _ lastIndex + 1.
  18175.                 self lastCharacterExtentSetX: 0.
  18176.                 ^ true].
  18177.         lastCharacter _ CR.
  18178.         characterPoint _ destX @ destY.
  18179.         self lastCharacterExtentSetX: rightMargin - destX.
  18180.         ^true! !
  18181.  
  18182. !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'di 11/7/97 12:20'!
  18183. crossedX
  18184.     "Text display has wrapping. The scanner just found a character past the x 
  18185.     location of the cursor. We know that the cursor is pointing at a character 
  18186.     or before one."
  18187.  
  18188.     | leadingTab currentX |
  18189.     characterPoint x <= (destX + ((lastCharacterExtent x) // 2))
  18190.         ifTrue:    [lastCharacter _ (text at: lastIndex).
  18191.                 characterPoint _ destX @ destY.
  18192.                 ^true].
  18193.     lastIndex >= line last 
  18194.         ifTrue:    [lastCharacter _ (text at: line last).
  18195.                 characterPoint _ destX @ destY.
  18196.                 ^true].
  18197.     "Pointing past middle of a character, return the next character."
  18198.     lastIndex _ lastIndex + 1.
  18199.     lastCharacter _ text at: lastIndex.
  18200.     currentX _ destX + lastCharacterExtent x.
  18201.     self lastCharacterExtentSetX: (font widthOf: lastCharacter).
  18202.     characterPoint _ currentX @ destY.
  18203.  
  18204.     "Yukky if next character is space or tab."
  18205.     (lastCharacter = Space and: [textStyle alignment = Justified])
  18206.         ifTrue:    [self lastCharacterExtentSetX:
  18207.                     (lastCharacterExtent x +     (line justifiedPadFor: (spaceCount + 1))).
  18208.                 ^ true].
  18209.     lastCharacter = Space
  18210.         ifTrue:
  18211.             ["See tabForDisplay for illumination on the following awfulness."
  18212.             leadingTab _ true.
  18213.             (line first to: lastIndex - 1) do:
  18214.             [:index |
  18215.             (text at: index) ~= Tab
  18216.                 ifTrue: [leadingTab _ false]].
  18217.             (textStyle alignment ~= Justified or: [leadingTab])
  18218.                 ifTrue:    [self lastCharacterExtentSetX: (textStyle nextTabXFrom: currentX
  18219.                             leftMargin: leftMargin rightMargin: rightMargin) -
  18220.                                 currentX]
  18221.                 ifFalse:    [self lastCharacterExtentSetX:  (((currentX + (textStyle tabWidth -
  18222.                                 (line justifiedTabDeltaFor: spaceCount))) -
  18223.                                     currentX) max: 0)]].
  18224.     ^ true
  18225. ! !
  18226.  
  18227. !CharacterBlockScanner methodsFor: 'stop conditions'!
  18228. endOfRun
  18229.     "Before arriving at the cursor location, the selection has encountered an 
  18230.     end of run. Answer false if the selection continues, true otherwise. Set 
  18231.     up indexes for building the appropriate CharacterBlock."
  18232.  
  18233.     | runLength lineStop |
  18234.     ((characterIndex ~~ nil and:
  18235.         [runStopIndex < characterIndex and: [runStopIndex < text size]])
  18236.             or:    [characterIndex == nil and: [lastIndex < line last]])
  18237.         ifTrue:    ["We're really at the end of a real run."
  18238.                 runLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).
  18239.                 characterIndex ~~ nil
  18240.                     ifTrue:    [lineStop _ characterIndex    "scanning for index"]
  18241.                     ifFalse:    [lineStop _ line last            "scanning for point"].
  18242.                 (runStopIndex _ lastIndex + (runLength - 1)) > lineStop
  18243.                     ifTrue:     [runStopIndex _ lineStop].
  18244.                 self setStopConditions.
  18245.                 ^false].
  18246.  
  18247.     lastCharacter _ text at: lastIndex.
  18248.     characterPoint _ destX @ destY.
  18249.     ((lastCharacter = Space and: [textStyle alignment = Justified])
  18250.         or: [lastCharacter = Tab and: [lastSpaceOrTabExtent notNil]])
  18251.         ifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent].
  18252.     characterIndex ~~ nil
  18253.         ifTrue:    ["If scanning for an index and we've stopped on that index,
  18254.                 then we back destX off by the width of the character stopped on
  18255.                 (it will be pointing at the right side of the character) and return"
  18256.                 runStopIndex = characterIndex
  18257.                     ifTrue:    [self characterPointSetX: destX - lastCharacterExtent x.
  18258.                             ^true].
  18259.                 "Otherwise the requested index was greater than the length of the
  18260.                 string.  Return string size + 1 as index, indicate further that off the
  18261.                 string by setting character to nil and the extent to 0."
  18262.                 lastIndex _  lastIndex + 1.
  18263.                 lastCharacter _ nil.
  18264.                 self lastCharacterExtentSetX: 0.
  18265.                 ^true].
  18266.  
  18267.     "Scanning for a point and either off the end of the line or off the end of the string."
  18268.     runStopIndex = text size
  18269.         ifTrue:    ["off end of string"
  18270.                 lastIndex _  lastIndex + 1.
  18271.                 lastCharacter _ nil.
  18272.                 self lastCharacterExtentSetX: 0.
  18273.                 ^true].
  18274.     "just off end of line without crossing x"
  18275.     lastIndex _ lastIndex + 1.
  18276.     ^true! !
  18277.  
  18278. !CharacterBlockScanner methodsFor: 'stop conditions'!
  18279. paddedSpace
  18280.     "When the line is justified, the spaces will not be the same as the font's 
  18281.     space character. A padding of extra space must be considered in trying 
  18282.     to find which character the cursor is pointing at. Answer whether the 
  18283.     scanning has crossed the cursor."
  18284.  
  18285.     | pad |
  18286.     pad _ 0.
  18287.     spaceCount _ spaceCount + 1.
  18288.     pad _ line justifiedPadFor: spaceCount.
  18289.     lastSpaceOrTabExtent _ lastCharacterExtent copy.
  18290.     self lastSpaceOrTabExtentSetX:  spaceWidth + pad.
  18291.     (destX + lastSpaceOrTabExtent x)  >= characterPoint x
  18292.         ifTrue: [lastCharacterExtent _ lastSpaceOrTabExtent copy.
  18293.                 ^self crossedX].
  18294.     lastIndex _ lastIndex + 1.
  18295.     destX _ destX + lastSpaceOrTabExtent x.
  18296.     ^ false
  18297. ! !
  18298.  
  18299. !CharacterBlockScanner methodsFor: 'stop conditions' stamp: 'di 11/11/97 08:50'!
  18300. setFont
  18301.     specialWidth _ nil.
  18302.     super setFont! !
  18303.  
  18304. !CharacterBlockScanner methodsFor: 'stop conditions'!
  18305. setStopConditions
  18306.     "Set the font and the stop conditions for the current run."
  18307.     
  18308.     self setFont.
  18309.     stopConditions at: (Space asciiValue + 1) put:
  18310.         (textStyle alignment = Justified ifTrue: [#paddedSpace] ifFalse: [nil])! !
  18311.  
  18312. !CharacterBlockScanner methodsFor: 'stop conditions'!
  18313. tab
  18314.     | currentX |
  18315.     currentX _ (textStyle alignment == Justified and: [self leadingTab not])
  18316.         ifTrue:        "imbedded tabs in justified text are weird"
  18317.             [destX + (textStyle tabWidth - (line justifiedTabDeltaFor: spaceCount)) max: destX]
  18318.         ifFalse:
  18319.             [textStyle
  18320.                 nextTabXFrom: destX
  18321.                 leftMargin: leftMargin
  18322.                 rightMargin: rightMargin].
  18323.     lastSpaceOrTabExtent _ lastCharacterExtent copy.
  18324.     self lastSpaceOrTabExtentSetX: (currentX - destX max: 0).
  18325.     currentX >= characterPoint x
  18326.         ifTrue: 
  18327.             [lastCharacterExtent _ lastSpaceOrTabExtent copy.
  18328.             ^ self crossedX].
  18329.     destX _ currentX.
  18330.     lastIndex _ lastIndex + 1.
  18331.     ^false! !
  18332.  
  18333.  
  18334. !CharacterBlockScanner methodsFor: 'private' stamp: 'di 12/2/97 14:30'!
  18335. buildCharacterBlockIn: para
  18336.     | lineIndex runLength lineStop done stopCondition |
  18337.     "handle nullText"
  18338.     (para numberOfLines = 0 or: [text size = 0])
  18339.         ifTrue:    [^ CharacterBlock new stringIndex: 1  "like being off end of string"
  18340.                     text: para text
  18341.                     topLeft: (para leftMarginForDisplayForLine: 1)
  18342.                                 @ para compositionRectangle top
  18343.                     extent: 0 @ textStyle lineGrid].
  18344.     "find the line"
  18345.     lineIndex _ para lineIndexOfTop: characterPoint y.
  18346.     destY _ para topAtLineIndex: lineIndex.
  18347.     line _ para lines at: lineIndex.
  18348.     rightMargin _ para rightMarginForDisplay.
  18349.  
  18350.     (lineIndex = para numberOfLines and:
  18351.         [(destY + line lineHeight) < characterPoint y])
  18352.             ifTrue:    ["if beyond lastLine, force search to last character"
  18353.                     self characterPointSetX: rightMargin]
  18354.             ifFalse:    [characterPoint y < (para compositionRectangle) top
  18355.                         ifTrue: ["force search to first line"
  18356.                                 characterPoint _ (para compositionRectangle) topLeft].
  18357.                     characterPoint x > rightMargin
  18358.                         ifTrue:    [self characterPointSetX: rightMargin]].
  18359.     destX _ leftMargin _ para leftMarginForDisplayForLine: lineIndex.
  18360.     nextLeftMargin_ para leftMarginForDisplayForLine: lineIndex+1.
  18361.     lastIndex _ line first.
  18362.  
  18363.     self setStopConditions.        "also sets font"
  18364.     runLength _ (text runLengthFor: line first).
  18365.     characterIndex ~~ nil
  18366.         ifTrue:    [lineStop _ characterIndex    "scanning for index"]
  18367.         ifFalse:    [lineStop _ line last].
  18368.     (runStopIndex _ lastIndex + (runLength - 1)) > lineStop
  18369.         ifTrue:    [runStopIndex _ lineStop].
  18370.     lastCharacterExtent _ 0 @ line lineHeight.
  18371.     spaceCount _ 0. done  _ false.
  18372.  
  18373.     [done]
  18374.     whileFalse:
  18375.     [stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex
  18376.             in: text string rightX: characterPoint x
  18377.             stopConditions: stopConditions kern: kern displaying: false.
  18378.  
  18379.     "see setStopConditions for stopping conditions for character block     operations."
  18380.     self lastCharacterExtentSetX: (font widthOf: (text at: lastIndex)).
  18381.     (self perform: stopCondition)
  18382.         ifTrue:    [^ CharacterBlock new stringIndex: lastIndex text: text
  18383.                     topLeft: characterPoint extent: lastCharacterExtent]]! !
  18384.  
  18385. !CharacterBlockScanner methodsFor: 'private'!
  18386. characterPointSetX: xVal
  18387.     characterPoint _ xVal @ characterPoint y! !
  18388.  
  18389. !CharacterBlockScanner methodsFor: 'private'!
  18390. lastCharacterExtentSetX: xVal
  18391.     lastCharacterExtent _ xVal @ lastCharacterExtent y! !
  18392.  
  18393. !CharacterBlockScanner methodsFor: 'private'!
  18394. lastSpaceOrTabExtentSetX: xVal
  18395.     lastSpaceOrTabExtent _ xVal @ lastSpaceOrTabExtent y! !
  18396. BitBlt subclass: #CharacterScanner
  18397.     instanceVariableNames: 'lastIndex xTable stopConditions text textStyle leftMargin rightMargin font line runStopIndex spaceCount spaceWidth emphasisCode kern '
  18398.     classVariableNames: ''
  18399.     poolDictionaries: 'TextConstants '
  18400.     category: 'Graphics-Support'!
  18401. !CharacterScanner commentStamp: 'di 5/22/1998 16:32' prior: 0!
  18402. CharacterScanner comment:
  18403. 'My instances hold the state associated with scanning text. My subclasses scan characters for specified purposes, such as computing a CharacterBlock or placing characters into Forms.'!
  18404.  
  18405.  
  18406. !CharacterScanner methodsFor: 'scanning' stamp: 'di 10/29/97 12:16'!
  18407. characterNotInFont
  18408.     "All fonts have an illegal character to be used when a character is not 
  18409.     within the font's legal range. When characters out of ranged are 
  18410.     encountered in scanning text, then this special character indicates the 
  18411.     appropriate behavior. The character is usually treated as a unary 
  18412.     message understood by a subclass of CharacterScanner."
  18413.  
  18414.     | illegalAsciiString saveIndex stopCondition | 
  18415.     saveIndex _ lastIndex.
  18416.     illegalAsciiString _ String with: (font maxAscii + 1) asCharacter.
  18417.     stopCondition _ self scanCharactersFrom: 1 to: 1
  18418.             in: illegalAsciiString
  18419.             rightX: rightMargin stopConditions: stopConditions
  18420.             kern: kern displaying: self doesDisplaying.
  18421.     lastIndex _ saveIndex + 1.
  18422.     stopCondition ~= (stopConditions at: EndOfRun)
  18423.         ifTrue:    [^self perform: stopCondition]
  18424.         ifFalse: [lastIndex = runStopIndex
  18425.                     ifTrue:    [^self perform: (stopConditions at: EndOfRun)].
  18426.                 ^false]
  18427. ! !
  18428.  
  18429. !CharacterScanner methodsFor: 'scanning' stamp: 'jm 11/19/97 23:15'!
  18430. ifCharIn: str at: i fits: segLen do: fonCharWidthBlock
  18431.     "Scan a character of text, tracking font changes, and return true,
  18432.     unless the character won't fit or it is off the end of the string."
  18433.     "No kerning yet..."
  18434.     | ascii char maxAscii |
  18435.     i > str size ifTrue: [^ false].
  18436.     (runStopIndex == nil or: [i > runStopIndex]) ifTrue:
  18437.         [runStopIndex _ i + (text runLengthFor: i) - 1.
  18438.         lastIndex _ i.
  18439.         self setFont].
  18440.     maxAscii _ xTable size-2.
  18441.     ascii _ (char _ str at: i) asciiValue min: maxAscii.
  18442.     width _ (xTable at: ascii + 2) - (xTable at: ascii + 1).
  18443.     width > segLen ifTrue: [^ false].
  18444.     fonCharWidthBlock value: font value: char value: width.
  18445.     ^ true! !
  18446.  
  18447. !CharacterScanner methodsFor: 'scanning'!
  18448. leadingTab
  18449.     "return true if only tabs lie to the left"
  18450.     line first to: lastIndex do:
  18451.         [:i | (text at: i) == Tab ifFalse: [^ false]].
  18452.     ^ true! !
  18453.  
  18454. !CharacterScanner methodsFor: 'scanning' stamp: 'di 11/17/97 15:08'!
  18455. placeEmbeddedObject: anchoredMorph
  18456.     "Place the anchoredMorph or return false if it cannot be placed.
  18457.     In any event, advance destX by its width."
  18458.  
  18459.     destX _ destX + (width _ anchoredMorph width).
  18460.     (destX > rightMargin and: [(leftMargin + width) <= rightMargin])
  18461.         ifTrue: ["Won't fit, but would on next line"
  18462.                 ^ false].
  18463.     runStopIndex _ lastIndex.  "Force new calc of emphasis"
  18464.     lastIndex _ lastIndex + 1.
  18465.     ^ true! !
  18466.  
  18467. !CharacterScanner methodsFor: 'scanning'!
  18468. scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops displaying: display 
  18469.     "Primitive. This is the inner loop of text display--but see 
  18470.     scanCharactersFrom: to:rightX: which would get the string, 
  18471.     stopConditions and displaying from the instance. March through source 
  18472.     String from startIndex to stopIndex. If any character is flagged with a 
  18473.     non-nil entry in stops, then return the corresponding value. Determine 
  18474.     width of each character from xTable. If dextX would exceed rightX, then 
  18475.     return stops at: 258. If displaying is true, then display the character. 
  18476.     Advance destX by the width of the character. If stopIndex has been 
  18477.     reached, then return stops at: 257. Fail under the same conditions that 
  18478.     the Smalltalk code below would cause an error. Optional. See Object 
  18479.     documentation whatIsAPrimitive."
  18480.     | ascii nextDestX maxAscii |
  18481.     <primitive: 103>
  18482.     maxAscii _ xTable size-2.
  18483.     lastIndex _ startIndex.
  18484.     [lastIndex <= stopIndex]
  18485.         whileTrue: 
  18486.             [ascii _ (sourceString at: lastIndex) asciiValue.
  18487.             "ascii > maxAscii ifTrue: [ascii _ maxAscii]."
  18488.             (stopConditions at: ascii + 1) == nil
  18489.                 ifFalse: [^stops at: ascii + 1].
  18490.             sourceX _ xTable at: ascii + 1.
  18491.             nextDestX _ destX + (width _ (xTable at: ascii + 2) - sourceX).
  18492.             nextDestX > rightX ifTrue: [^stops at: CrossedX].
  18493.             display ifTrue: [self copyBits].
  18494.             destX _ nextDestX.
  18495.             lastIndex _ lastIndex + 1].
  18496.     lastIndex _ stopIndex.
  18497.     ^stops at: EndOfRun! !
  18498.  
  18499. !CharacterScanner methodsFor: 'scanning' stamp: 'di 10/31/97 12:51'!
  18500. scanCharactersFrom: startIndex to: stopIndex in: sourceString rightX: rightX stopConditions: stops kern: kernDelta displaying: display 
  18501.     "This method will perform text scanning with non-zero kerning.
  18502.     It calls the faster primitive method, if the kern delta is zero.
  18503.     Some day we may want to put kerning into the primitive."
  18504.     | ascii nextDestX maxAscii fillBlt |
  18505.     kernDelta = 0 ifTrue:
  18506.         [^ self scanCharactersFrom: startIndex to: stopIndex in: sourceString
  18507.                 rightX: rightX stopConditions: stops displaying: display].
  18508.     display ifTrue: [fillBlt _ self fillBlt].
  18509.     maxAscii _ xTable size-2.
  18510.     lastIndex _ startIndex.
  18511.     [lastIndex <= stopIndex]
  18512.         whileTrue: 
  18513.             [ascii _ (sourceString at: lastIndex) asciiValue.
  18514.             ascii > maxAscii ifTrue: [ascii _ maxAscii].
  18515.             (stopConditions at: ascii + 1) == nil
  18516.                 ifFalse: [^stops at: ascii + 1].
  18517.             sourceX _ xTable at: ascii + 1.
  18518.             nextDestX _ destX + (width _ (xTable at: ascii + 2) - sourceX).
  18519.             nextDestX > rightX ifTrue: [^stops at: CrossedX].
  18520.             display ifTrue:
  18521.                 [self copyBits
  18522.                 fillBlt == nil ifFalse:
  18523.                     [fillBlt destX: nextDestX destY: destY
  18524.                             width: kernDelta height: height;
  18525.                             copyBits]].
  18526.             destX _ nextDestX + kernDelta.
  18527.             lastIndex _ lastIndex + 1].
  18528.     lastIndex _ stopIndex.
  18529.     ^stops at: EndOfRun! !
  18530.  
  18531.  
  18532. !CharacterScanner methodsFor: 'private'!
  18533. addEmphasis: code
  18534.     "Set the bold-ital-under-strike emphasis."
  18535.     emphasisCode _ emphasisCode bitOr: code! !
  18536.  
  18537. !CharacterScanner methodsFor: 'private' stamp: 'di 10/29/97 11:58'!
  18538. addKern: kernDelta
  18539.     "Set the current kern amount."
  18540.     kern _ kern + kernDelta! !
  18541.  
  18542. !CharacterScanner methodsFor: 'private' stamp: 'jm 11/19/97 21:56'!
  18543. beginAt: startCharIndex
  18544.     lastIndex _ startCharIndex.
  18545.     runStopIndex _ lastIndex + (text runLengthFor: lastIndex) - 1.
  18546.     self setFont! !
  18547.  
  18548. !CharacterScanner methodsFor: 'private'!
  18549. doesDisplaying
  18550.  
  18551.     ^false! !
  18552.  
  18553. !CharacterScanner methodsFor: 'private' stamp: 'jm 11/19/97 21:56'!
  18554. ifNextCharFits: segLen do: fonCharWidthBlock! !
  18555.  
  18556. !CharacterScanner methodsFor: 'private'!
  18557. initializeFromParagraph: aParagraph clippedBy: clippingRectangle
  18558.  
  18559.     text _ aParagraph text.
  18560.     textStyle _ aParagraph textStyle. 
  18561.     destForm _ aParagraph destinationForm.
  18562.     self fillColor: aParagraph fillColor.    "sets halftoneForm"
  18563.     self combinationRule: aParagraph rule.
  18564.     self clipRect: clippingRectangle.
  18565.     sourceY _ 0! !
  18566.  
  18567. !CharacterScanner methodsFor: 'private'!
  18568. setActualFont: aFont
  18569.     "Set the basal font to an isolated font reference."
  18570.  
  18571.     font _ aFont! !
  18572.  
  18573. !CharacterScanner methodsFor: 'private' stamp: 'di 10/29/97 12:00'!
  18574. setFont
  18575.     "Set the font and other emphasis."
  18576.     self setFont: 1.
  18577.     emphasisCode _ 0.
  18578.     kern _ 0.
  18579.     (text attributesAt: lastIndex) do: 
  18580.         [:att | att emphasizeScanner: self].
  18581.     font _ font emphasized: emphasisCode.
  18582.  
  18583.     "Install various parameters from the font."
  18584.     spaceWidth _ font widthOf: Space. 
  18585.     sourceForm _ font glyphs.  "Should only be needed in DisplayScanner"
  18586.     height _ font height.            " ditto "
  18587.     xTable _ font xTable.
  18588.     stopConditions _ font stopConditions.
  18589.     stopConditions at: Space asciiValue + 1 put: #space.
  18590.     stopConditions at: Tab asciiValue + 1 put: #tab.
  18591.     stopConditions at: CR asciiValue + 1 put: #cr.
  18592.     stopConditions at: EndOfRun put: #endOfRun.
  18593.     stopConditions at: CrossedX put: #crossedX! !
  18594.  
  18595. !CharacterScanner methodsFor: 'private' stamp: 'di 10/24/97 09:05'!
  18596. setFont: fontNumber
  18597.     "Set the font by number from the textStyle."
  18598.  
  18599.     self setActualFont: (textStyle fontAt: fontNumber)! !
  18600.  
  18601. !CharacterScanner methodsFor: 'private' stamp: 'jm 11/19/97 20:51'!
  18602. setFontAt: startCharIndex
  18603.     lastIndex _ startCharIndex.
  18604.     self setFont! !
  18605.  
  18606. !CharacterScanner methodsFor: 'private' stamp: 'di 10/22/97 11:52'!
  18607. text: t textStyle: ts
  18608.     text _ t.
  18609.     textStyle _ ts! !
  18610.  
  18611. !CharacterScanner methodsFor: 'private'!
  18612. textColor: ignored
  18613.     "Overridden in DisplayScanner"! !
  18614. ServerAction subclass: #ChatPage
  18615.     instanceVariableNames: 'current '
  18616.     classVariableNames: ''
  18617.     poolDictionaries: ''
  18618.     category: 'PluggableWebServer'!
  18619. !ChatPage commentStamp: 'di 5/22/1998 16:32' prior: 0!
  18620. Simple ServerAction that allows a primitive chat session shown as a web page.  It maintains a list of the 20 most recent submissions.  There is a form on the page for typing your contribution to the session. 
  18621.  
  18622. The default Swiki has a chat page enabled.
  18623.  
  18624. Get to the page by this URL:
  18625. machine:80/chat!
  18626.  
  18627.  
  18628. !ChatPage methodsFor: 'chat processing' stamp: 'mjg 11/25/97 13:33'!
  18629. add: aMessage 
  18630.     current isNil ifTrue: [current _ OrderedCollection new].
  18631.     current add: aMessage.
  18632.     (current size > 20) 
  18633.         ifTrue: [current _ current copyFrom: (current size - 20) to: (current size)]! !
  18634.  
  18635. !ChatPage methodsFor: 'chat processing' stamp: 'mjg 11/17/97 13:32'!
  18636. current
  18637.     ^current
  18638. ! !
  18639.  
  18640.  
  18641. !ChatPage methodsFor: 'URL processing' stamp: 'mjg 11/25/97 13:34'!
  18642. process: request 
  18643.     | author note |
  18644.     request fields isNil
  18645.         ifTrue: 
  18646.             [current isNil ifTrue: [current _ OrderedCollection new].
  18647.             request reply: (HTMLformatter evalEmbedded: (self fileContents: 'chat.html')
  18648.                     with: current)]
  18649.         ifFalse: 
  18650.             [author _ request fields at: 'author'.
  18651.             note _ request fields at: 'note'.
  18652.             self add: '<b>' , author , '</b> 
  18653.             <i>' , Time now printString , '-' , Date today printString , '</i><p>' , note , '<p>'.
  18654.             request fields at: 'current' put: current.
  18655.             request reply: (HTMLformatter evalEmbedded: (self fileContents: 'chat.html')
  18656.                     with: request)]! !
  18657. Arc subclass: #Circle
  18658.     instanceVariableNames: ''
  18659.     classVariableNames: ''
  18660.     poolDictionaries: ''
  18661.     category: 'Graphics-Paths'!
  18662. !Circle commentStamp: 'di 5/22/1998 16:32' prior: 0!
  18663. Circle comment:
  18664. 'I represent a full circle. I am made from four Arcs.'!
  18665.  
  18666.  
  18667. !Circle methodsFor: 'displaying'!
  18668. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
  18669.  
  18670.     1 to: 4 do:
  18671.         [:i |
  18672.         super quadrant: i.
  18673.         super displayOn: aDisplayMedium
  18674.             at: aPoint
  18675.             clippingBox: clipRect
  18676.             rule: anInteger
  18677.             fillColor: aForm]! !
  18678.  
  18679. !Circle methodsFor: 'displaying'!
  18680. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  18681.  
  18682.     1 to: 4 do:
  18683.         [:i |
  18684.         super quadrant: i.
  18685.         super displayOn: aDisplayMedium
  18686.             transformation: aTransformation
  18687.             clippingBox: clipRect
  18688.             rule: anInteger
  18689.             fillColor: aForm]! !
  18690.  
  18691.  
  18692. !Circle methodsFor: 'display box access'!
  18693. computeBoundingBox
  18694.  
  18695.     ^center - radius + form offset extent: form extent + (radius * 2) asPoint! !
  18696.  
  18697. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  18698.  
  18699. Circle class
  18700.     instanceVariableNames: ''!
  18701.  
  18702. !Circle class methodsFor: 'examples'!
  18703. exampleOne 
  18704.     "Click any button somewhere on the screen. The point will be the center
  18705.     of the circcle of radius 150."
  18706.  
  18707.     | aCircle aForm |
  18708.     aForm _ Form extent: 1@30.
  18709.     aForm fillBlack.
  18710.     aCircle _ Circle new.
  18711.     aCircle form: aForm.
  18712.     aCircle radius: 150.
  18713.     aCircle center: Sensor waitButton.
  18714.     aCircle displayOn: Display
  18715.     
  18716.     "Circle exampleOne"! !
  18717.  
  18718. !Circle class methodsFor: 'examples'!
  18719. exampleTwo
  18720.     "Designate a rectangular area that should be used as the brush for
  18721.     displaying the circle. Click any button at a point on the screen which
  18722.     will be the center location for the circle. The curve will be displayed
  18723.     with a long black form."
  18724.  
  18725.     | aCircle aForm |
  18726.     aForm _ Form fromUser.
  18727.     aCircle _ Circle new.
  18728.     aCircle form: aForm.
  18729.     aCircle radius: 150.
  18730.     aCircle center: Sensor waitButton.
  18731.     aCircle displayOn: Display at: 0 @ 0 rule: Form reverse
  18732.  
  18733.      "Circle exampleTwo"! !
  18734. ClassDescription subclass: #Class
  18735.     instanceVariableNames: 'name classPool sharedPools '
  18736.     classVariableNames: ''
  18737.     poolDictionaries: ''
  18738.     category: 'Kernel-Classes'!
  18739. !Class commentStamp: 'di 5/22/1998 16:32' prior: 0!
  18740. Class comment:
  18741. 'My instances describe the representation and behavior of objects. I add more comprehensive programming support facilities to the basic attributes of Behavior and the descriptive facilities of ClassDescription. An example is accessing shared (pool) variables.'!
  18742.  
  18743.  
  18744. !Class methodsFor: 'initialize-release'!
  18745. declare: varString 
  18746.     "Declare class variables common to all instances. Answer whether 
  18747.     recompilation is advisable."
  18748.  
  18749.     | newVars conflicts assoc class |
  18750.     newVars _ 
  18751.         (Scanner new scanFieldNames: varString)
  18752.             collect: [:x | x asSymbol].
  18753.     newVars do:
  18754.         [:var | var first isLowercase
  18755.             ifTrue: [self error: var, ' class variable name should be capitalized; proceed to include anyway.']].
  18756.     conflicts _ false.
  18757.     classPool == nil 
  18758.         ifFalse: [(classPool keys reject: [:x | newVars includes: x]) do: 
  18759.                     [:var | self removeClassVarName: var]].
  18760.     (newVars reject: [:var | self classPool includesKey: var])
  18761.         do: [:var | "adding"
  18762.             "check if new vars defined elsewhere"
  18763.             (self scopeHas: var ifTrue: [:ignored | ignored])
  18764.                 ifTrue: 
  18765.                     [self error: var , ' is defined elsewhere'.
  18766.                     conflicts _ true]].
  18767.     newVars size > 0
  18768.         ifTrue: 
  18769.             [classPool _ self classPool.
  18770.             "in case it was nil"
  18771.             newVars do: [:var | classPool declare: var from: Undeclared]].
  18772.     ^conflicts! !
  18773.  
  18774. !Class methodsFor: 'initialize-release'!
  18775. obsolete
  18776.     "Change the receiver to an obsolete class by changing its name to have
  18777.     the prefix -AnObsolete-."
  18778.  
  18779.     name _ 'AnObsolete' , name.
  18780.     classPool _ Dictionary new.
  18781.     self class obsolete.
  18782.     super obsolete! !
  18783.  
  18784. !Class methodsFor: 'initialize-release'!
  18785. removeFromSystem
  18786.     "Forget the receiver from the Smalltalk global dictionary. Any existing 
  18787.     instances will refer to an obsolete version of the receiver."
  18788.  
  18789.     Smalltalk removeClassFromSystem: self.
  18790.     self obsolete! !
  18791.  
  18792. !Class methodsFor: 'initialize-release'!
  18793. sharing: poolString 
  18794.     "Set up sharedPools. Answer whether recompilation is advisable."
  18795.     | oldPools found |
  18796.     oldPools _ self sharedPools.
  18797.     sharedPools _ OrderedCollection new.
  18798.     (Scanner new scanFieldNames: poolString) do: 
  18799.         [:poolName | 
  18800.         sharedPools add: (Smalltalk at: poolName asSymbol)].
  18801.     sharedPools isEmpty ifTrue: [sharedPools _ nil].
  18802.     oldPools do: [:pool | found _ false.
  18803.                 self sharedPools do: [:p | p == pool ifTrue: [found _ true]].
  18804.                 found ifFalse: [^ true "A pool got deleted"]].
  18805.     ^ false! !
  18806.  
  18807. !Class methodsFor: 'initialize-release'!
  18808. superclass: sup methodDict: md format: ft name: nm organization: org instVarNames: nilOrArray classPool: pool sharedPools: poolSet 
  18809.     "Answer an instance of me, a new class, using the arguments of the 
  18810.     message as the needed information."
  18811.  
  18812.     superclass _ sup.
  18813.     methodDict _ md.
  18814.     format _ ft.
  18815.     name _ nm.
  18816.     organization _ org.
  18817.     instanceVariables _ nilOrArray.
  18818.     classPool _ pool.
  18819.     sharedPools _ poolSet! !
  18820.  
  18821. !Class methodsFor: 'initialize-release'!
  18822. validateFrom: oldClass in: environ instanceVariableNames: invalidFields methods: invalidMethods 
  18823.     "Recompile the receiver and redefine its subclasses if necessary."
  18824.  
  18825.     super
  18826.         validateFrom: oldClass
  18827.         in: environ
  18828.         instanceVariableNames: invalidFields
  18829.         methods: invalidMethods.
  18830.     self ~~ oldClass
  18831.         ifTrue: 
  18832.             [environ at: name put: self.
  18833.             oldClass obsolete]! !
  18834.  
  18835.  
  18836. !Class methodsFor: 'accessing'!
  18837. classPool
  18838.     "Answer the dictionary of class variables."
  18839.  
  18840.     classPool == nil
  18841.         ifTrue: [^Dictionary new]
  18842.         ifFalse: [^classPool]! !
  18843.  
  18844. !Class methodsFor: 'accessing'!
  18845. name
  18846.     "Answer the name of the receiver."
  18847.  
  18848.     name == nil
  18849.         ifTrue: [^super name]
  18850.         ifFalse: [^name]! !
  18851.  
  18852.  
  18853. !Class methodsFor: 'testing'!
  18854. hasMethods
  18855.     "Answer a Boolean according to whether any methods are defined for the 
  18856.     receiver (includes whether there are methods defined in the receiver's 
  18857.     metaclass)."
  18858.  
  18859.     ^super hasMethods or: [self class hasMethods]! !
  18860.  
  18861.  
  18862. !Class methodsFor: 'copying'!
  18863. copy
  18864.     | newClass |
  18865.     newClass _ self class copy new
  18866.         superclass: superclass
  18867.         methodDict: methodDict copy
  18868.         format: format
  18869.         name: name
  18870.         organization: organization copy
  18871.         instVarNames: instanceVariables copy
  18872.         classPool: classPool copy
  18873.         sharedPools: sharedPools.
  18874.     Class instSize+1 to: self class instSize do:
  18875.         [:offset | newClass instVarAt: offset put: (self instVarAt: offset)].
  18876.     ^ newClass! !
  18877.  
  18878. !Class methodsFor: 'copying'!
  18879. copyForValidation
  18880.     "Make a copy of the receiver (a class) but do not install the created class 
  18881.     as a new class in the system. This is used for creating a new version of 
  18882.     the receiver in which the installation is deferred until all changes are 
  18883.     successfully completed."
  18884.     | newClass |
  18885.     newClass _ self class copy new
  18886.         superclass: superclass
  18887.         methodDict: methodDict copy
  18888.         format: format
  18889.         name: name
  18890.         organization: organization
  18891.         instVarNames: instanceVariables copy
  18892.         classPool: classPool
  18893.         sharedPools: sharedPools.
  18894.     Class instSize+1 to: self class instSize do:
  18895.         [:offset | newClass instVarAt: offset put: (self instVarAt: offset)].
  18896.     ^ newClass! !
  18897.  
  18898. !Class methodsFor: 'copying' stamp: 'sw 6/12/96'!
  18899. copyOfMethodDictionary
  18900.     "Return a copy of the receiver's method dictionary.  "
  18901.  
  18902.     ^ methodDict copy! !
  18903.  
  18904.  
  18905. !Class methodsFor: 'class name' stamp: 'tk 3/10/98 08:15'!
  18906. rename: aString 
  18907.     "The new name of the receiver is the argument, aString."
  18908.  
  18909.     | newName |
  18910.     newName _ aString asSymbol.
  18911.     (Smalltalk includesKey: newName)
  18912.         ifTrue: [^self error: newName , ' already exists'].
  18913.     (Undeclared includesKey: newName)
  18914.         ifTrue: [^ SelectionMenu notify: 'There are references to, ' , aString printString , '
  18915. from Undeclared. Check them after this change.'].
  18916.     Smalltalk renameClass: self as: newName.
  18917.     name _ newName.
  18918.     self comment: self comment.
  18919. ! !
  18920.  
  18921.  
  18922. !Class methodsFor: 'instance variables'!
  18923. addInstVarName: aString
  18924.     "Add the argument, aString, as one of the receiver's instance variables."
  18925.  
  18926.     superclass class
  18927.         name: self name
  18928.         inEnvironment: Smalltalk
  18929.         subclassOf: superclass
  18930.         instanceVariableNames: self instanceVariablesString , aString
  18931.         variable: self isVariable
  18932.         words: self isWords
  18933.         pointers: self isPointers
  18934.         classVariableNames: self classVariablesString
  18935.         poolDictionaries: self sharedPoolsString
  18936.         category: self category
  18937.         comment: nil
  18938.         changed: false! !
  18939.  
  18940. !Class methodsFor: 'instance variables'!
  18941. removeInstVarName: aString 
  18942.     "Remove the argument, aString, as one of the receiver's instance variables."
  18943.  
  18944.     | newInstVarString |
  18945.     (self instVarNames includes: aString)
  18946.         ifFalse: [self error: aString , ' is not one of my instance variables'].
  18947.     newInstVarString _ ''.
  18948.     (self instVarNames copyWithout: aString) do: 
  18949.         [:varName | newInstVarString _ newInstVarString , ' ' , varName].
  18950.     superclass class
  18951.         name: self name
  18952.         inEnvironment: Smalltalk
  18953.         subclassOf: superclass
  18954.         instanceVariableNames: newInstVarString
  18955.         variable: self isVariable
  18956.         words: self isWords
  18957.         pointers: self isPointers
  18958.         classVariableNames: self classVariablesString
  18959.         poolDictionaries: self sharedPoolsString
  18960.         category: self category
  18961.         comment: nil
  18962.         changed: false! !
  18963.  
  18964.  
  18965. !Class methodsFor: 'class variables'!
  18966. addClassVarName: aString 
  18967.     "Add the argument, aString, as a class variable of the receiver.
  18968.     Signal an error if the first character of aString is not capitalized,
  18969.     or if it is already a variable named in the class."
  18970.     | symbol index |
  18971.     aString first isLowercase
  18972.         ifTrue: [^self error: aString, ' class variable name should be capitalized; proceed to include anyway.'].
  18973.     symbol _ aString asSymbol.
  18974.     self withAllSubclasses do: 
  18975.         [:subclass | 
  18976.         subclass scopeHas: symbol
  18977.             ifTrue: [:temp | 
  18978.                     ^ self error: aString 
  18979.                         , ' is already used as a variable name in class ' 
  18980.                         , subclass name]].
  18981.     classPool == nil ifTrue: [classPool _ Dictionary new].
  18982.     (classPool includesKey: symbol) ifFalse: 
  18983.         ["Pick up any refs in Undeclared"
  18984.         classPool declare: symbol from: Undeclared.
  18985.         Smalltalk changes changeClass: self]! !
  18986.  
  18987. !Class methodsFor: 'class variables'!
  18988. allClassVarNames
  18989.     "Answer a Set of the names of the receiver's class variables, including those
  18990.     defined in the superclasses of the receiver."
  18991.  
  18992.     | aSet |
  18993.     superclass == nil
  18994.         ifTrue: 
  18995.             [^self classVarNames]  "This is the keys so it is a new Set."
  18996.         ifFalse: 
  18997.             [aSet _ superclass allClassVarNames.
  18998.             aSet addAll: self classVarNames.
  18999.             ^aSet]! !
  19000.  
  19001. !Class methodsFor: 'class variables'!
  19002. classVarNames
  19003.     "Answer a Set of the names of the class variables defined in the receiver."
  19004.  
  19005.     ^self classPool keys! !
  19006.  
  19007. !Class methodsFor: 'class variables' stamp: 'tk 3/15/98 20:19'!
  19008. ensureClassPool
  19009.  
  19010.     classPool ifNil: [classPool _ Dictionary new].! !
  19011.  
  19012. !Class methodsFor: 'class variables'!
  19013. initialize
  19014.     "Typically used for the initialization of class variables and metaclass 
  19015.     instance variables. Does nothing, but may be overridden in Metaclasses."
  19016.  
  19017.     ^self! !
  19018.  
  19019. !Class methodsFor: 'class variables'!
  19020. removeClassVarName: aString 
  19021.     "Remove the class variable whose name is the argument, aString, from 
  19022.     the names defined in the receiver, a class. Create an error notification if 
  19023.     aString is not a class variable or if it is still being used in the code of 
  19024.     the class."
  19025.  
  19026.     | anAssoc aSymbol |
  19027.     aSymbol _ aString asSymbol.
  19028.     (classPool includesKey: aSymbol)
  19029.         ifFalse: [^self error: aString, ' is not a class variable'].
  19030.     anAssoc _ classPool associationAt: aSymbol.
  19031.     self withAllSubclasses do:
  19032.         [:subclass |
  19033.         (Array with: subclass with: subclass class) do:
  19034.             [:classOrMeta |
  19035.             (classOrMeta whichSelectorsReferTo: (classPool associationAt: aSymbol))
  19036.                 isEmpty
  19037.                     ifFalse: [^self error: aString
  19038.                                 , ' is still used in code of class '
  19039.                                 , classOrMeta name]]].
  19040.     classPool removeKey: aSymbol! !
  19041.  
  19042.  
  19043. !Class methodsFor: 'pool variables'!
  19044. addSharedPool: aDictionary 
  19045.     "Add the argument, aDictionary, as one of the receiver's pool dictionaries. 
  19046.     Create an error if the dictionary is already one of the pools."
  19047.  
  19048.     (self sharedPools includes: aDictionary)
  19049.         ifTrue: [^self error: 'The dictionary is already in my pool'].
  19050.     sharedPools == nil
  19051.         ifTrue: [sharedPools _ OrderedCollection with: aDictionary]
  19052.         ifFalse: [sharedPools add: aDictionary]! !
  19053.  
  19054. !Class methodsFor: 'pool variables'!
  19055. allSharedPools
  19056.     "Answer a Set of the pools the receiver shares, including those defined 
  19057.     in the superclasses of the receiver."
  19058.  
  19059.     | aSet |
  19060.     superclass == nil
  19061.         ifTrue:
  19062.             [^self sharedPools copy]
  19063.         ifFalse: 
  19064.             [aSet _ superclass allSharedPools.
  19065.             aSet addAll: self sharedPools.
  19066.             ^aSet]! !
  19067.  
  19068. !Class methodsFor: 'pool variables' stamp: 'tk 9/12/96'!
  19069. removeSharedPool: aDictionary 
  19070.     "Remove the pool dictionary, aDictionary, as one of the receiver's pool 
  19071.     dictionaries. Create an error notification if the dictionary is not one of 
  19072.     the pools.
  19073.     : Note that it removes the wrong one if there are two empty Dictionaries in the list."
  19074.  
  19075.     | satisfiedSet workingSet aSubclass |
  19076.     (self sharedPools includes: aDictionary)
  19077.         ifFalse: [^self error: 'the dictionary is not in my pool'].
  19078.  
  19079.     "first see if it is declared in a superclass in which case we can remove it."
  19080.     (self selectSuperclasses: [:class | class sharedPools includes: aDictionary]) isEmpty
  19081.         ifFalse: [sharedPools remove: aDictionary.
  19082.                 sharedPools isEmpty ifTrue: [sharedPools _ nil].
  19083.                 ^self]. 
  19084.  
  19085.     "second get all the subclasses that reference aDictionary through me rather than a 
  19086.     superclass that is one of my subclasses."
  19087.  
  19088.     workingSet _ self subclasses asOrderedCollection.
  19089.     satisfiedSet _ Set new.
  19090.     [workingSet isEmpty] whileFalse:
  19091.         [aSubclass _ workingSet removeFirst.
  19092.         (aSubclass sharedPools includes: aDictionary)
  19093.             ifFalse: 
  19094.                 [satisfiedSet add: aSubclass.
  19095.                 workingSet addAll: aSubclass subclasses]].
  19096.  
  19097.     "for each of these, see if they refer to any of the variables in aDictionary because 
  19098.     if they do, we can not remove the dictionary."
  19099.     satisfiedSet add: self.
  19100.     satisfiedSet do: 
  19101.         [:sub | 
  19102.         aDictionary associationsDo: 
  19103.             [:aGlobal | 
  19104.             (sub whichSelectorsReferTo: aGlobal) isEmpty 
  19105.                 ifFalse: [^self error: aGlobal key 
  19106.                                 , ' is still used in code of class '
  19107.                                 , sub name]]].
  19108.     sharedPools remove: aDictionary.
  19109.     sharedPools isEmpty ifTrue: [sharedPools _ nil]! !
  19110.  
  19111. !Class methodsFor: 'pool variables'!
  19112. sharedPools
  19113.     "Answer a Set of the pool dictionaries declared in the receiver."
  19114.  
  19115.     sharedPools == nil
  19116.         ifTrue: [^OrderedCollection new]
  19117.         ifFalse: [^sharedPools]! !
  19118.  
  19119.  
  19120. !Class methodsFor: 'compiling'!
  19121. compileAllFrom: oldClass
  19122.     "Recompile all the methods in the receiver's method dictionary (not the
  19123.     subclasses). Also recompile the methods in the metaclass."
  19124.  
  19125.     super compileAllFrom: oldClass.
  19126.     self class compileAllFrom: oldClass class! !
  19127.  
  19128. !Class methodsFor: 'compiling'!
  19129. possibleVariablesFor: misspelled continuedFrom: oldResults
  19130.  
  19131.     | results |
  19132.     results _ misspelled correctAgainstDictionary: self classPool continuedFrom: oldResults.
  19133.     self sharedPools do: [:pool | 
  19134.         results _ misspelled correctAgainstDictionary: pool continuedFrom: results ].
  19135.     superclass == nil
  19136.         ifTrue: 
  19137.             [ ^ misspelled correctAgainstDictionary: Smalltalk continuedFrom: results ]
  19138.         ifFalse:
  19139.             [ ^ superclass possibleVariablesFor: misspelled continuedFrom: results ]! !
  19140.  
  19141. !Class methodsFor: 'compiling' stamp: 'tk 9/11/96'!
  19142. scopeHas: varName ifTrue: assocBlock 
  19143.     "Look up the first argument, varName, in the context of the receiver. If it is there,
  19144.     pass the association to the second argument, assocBlock, and answer true.
  19145.     Else answer false.
  19146.     : Allow key in shared pools to be a string for HyperSqueak"
  19147.  
  19148.     | assoc |
  19149.     assoc _ self classPool associationAt: varName ifAbsent: [].
  19150.     assoc == nil
  19151.         ifFalse: 
  19152.             [assocBlock value: assoc.
  19153.             ^true].
  19154.     self sharedPools do: 
  19155.         [:pool | 
  19156.         varName = #Textual ifTrue: [self halt].
  19157.         assoc _ pool associationAt: varName ifAbsent: [
  19158.             pool associationAt: varName asString ifAbsent: []].
  19159.         assoc == nil
  19160.             ifFalse: 
  19161.                 [assocBlock value: assoc.
  19162.                 ^true]].
  19163.     superclass == nil
  19164.         ifTrue: 
  19165.             [assoc _ Smalltalk associationAt: varName ifAbsent: [].
  19166.             assoc == nil
  19167.                 ifFalse: 
  19168.                     [assocBlock value: assoc.
  19169.                     ^true].
  19170.             ^false].
  19171.     ^superclass scopeHas: varName ifTrue: assocBlock! !
  19172.  
  19173.  
  19174. !Class methodsFor: 'subclass creation' stamp: 'sw 5/19/1998 09:07'!
  19175. newSubclass
  19176.     | i className |
  19177.     i _ 1.
  19178.     [className _ (self name , i printString) asSymbol.
  19179.      Smalltalk includesKey: className]
  19180.         whileTrue: [i _ i + 1].
  19181.  
  19182.     ^ self subclass: className
  19183.         instanceVariableNames: ''
  19184.         classVariableNames: ''
  19185.         poolDictionaries: ''
  19186.         category: 'UserObjects'
  19187.  
  19188. "Point newSubclass new"! !
  19189.  
  19190. !Class methodsFor: 'subclass creation'!
  19191. subclass: t instanceVariableNames: f classVariableNames: d poolDictionaries: s category: cat 
  19192.     "This is the standard initialization message for creating a new class as a 
  19193.     subclass of an existing class (the receiver)."
  19194.  
  19195.     self isVariable
  19196.         ifTrue: 
  19197.             [self isPointers 
  19198.                 ifTrue: [^self
  19199.                             variableSubclass: t
  19200.                             instanceVariableNames: f
  19201.                             classVariableNames: d
  19202.                             poolDictionaries: s
  19203.                             category: cat].
  19204.             self isBytes 
  19205.                 ifTrue: [^self
  19206.                             variableByteSubclass: t
  19207.                             instanceVariableNames: f
  19208.                             classVariableNames: d
  19209.                             poolDictionaries: s
  19210.                             category: cat].
  19211.             ^self
  19212.                 variableWordSubclass: t
  19213.                 instanceVariableNames: f
  19214.                 classVariableNames: d
  19215.                 poolDictionaries: s
  19216.                 category: cat].
  19217.     ^self class
  19218.         name: t
  19219.         inEnvironment: Smalltalk
  19220.         subclassOf: self
  19221.         instanceVariableNames: f
  19222.         variable: false
  19223.         words: true
  19224.         pointers: true
  19225.         classVariableNames: d
  19226.         poolDictionaries: s
  19227.         category: cat
  19228.         comment: nil
  19229.         changed: false! !
  19230.  
  19231. !Class methodsFor: 'subclass creation'!
  19232. variableByteSubclass: t instanceVariableNames: f 
  19233.     classVariableNames: d poolDictionaries: s category: cat
  19234.     "This is the standard initialization message for creating a new class as a 
  19235.     subclass of an existing class (the receiver) in which the subclass is to 
  19236.     have indexable byte-sized nonpointer variables."
  19237.  
  19238.     self instSize > 0 
  19239.         ifTrue: [^self error: 'cannot make a byte subclass of a class with named fields'].
  19240.     (self isVariable and: [self isWords])
  19241.         ifTrue: [^self error: 'cannot make a byte subclass of a class with word fields'].
  19242.     (self isVariable and: [self isPointers])
  19243.         ifTrue: [^self error: 
  19244.                     'cannot make a byte subclass of a class with pointer fields'].
  19245.     ^self class name: t 
  19246.         inEnvironment: Smalltalk
  19247.         subclassOf: self 
  19248.         instanceVariableNames: f
  19249.         variable: true 
  19250.         words: false 
  19251.         pointers: false
  19252.         classVariableNames: d 
  19253.         poolDictionaries: s 
  19254.         category: cat 
  19255.         comment: nil
  19256.         changed: false! !
  19257.  
  19258. !Class methodsFor: 'subclass creation'!
  19259. variableSubclass: t instanceVariableNames: f 
  19260.     classVariableNames: d poolDictionaries: s category: cat
  19261.     "This is the standard initialization message for creating a new class as a 
  19262.     subclass of an existing class (the receiver) in which the subclass is to 
  19263.     have indexable pointer variables."
  19264.  
  19265.     self isBits 
  19266.         ifTrue: 
  19267.             [^self error: 
  19268.                 'cannot make a pointer subclass of a class with non-pointer fields'].
  19269.     ^self class name: t 
  19270.         inEnvironment: Smalltalk
  19271.         subclassOf: self 
  19272.         instanceVariableNames: f
  19273.         variable: true 
  19274.         words: true 
  19275.         pointers: true
  19276.         classVariableNames: d 
  19277.         poolDictionaries: s 
  19278.         category: cat 
  19279.         comment: nil
  19280.         changed: false! !
  19281.  
  19282. !Class methodsFor: 'subclass creation'!
  19283. variableWordSubclass: t instanceVariableNames: f 
  19284.     classVariableNames: d poolDictionaries: s category: cat
  19285.     "This is the standard initialization message for creating a new class as a 
  19286.     subclass of an existing class (the receiver) in which the subclass is to 
  19287.     have indexable word-sized nonpointer variables."
  19288.  
  19289.     self instSize > 0 
  19290.         ifTrue: [^self error: 
  19291.                     'cannot make a word subclass of a class with named fields'].
  19292.     self isBytes
  19293.         ifTrue: [^self error: 'cannot make a word subclass of a class with byte fields'].
  19294.     (self isVariable and: [self isPointers])
  19295.         ifTrue: [^self error: 
  19296.                     'cannot make a word subclass of a class with pointer fields'].
  19297.     ^self class name: t 
  19298.         inEnvironment: Smalltalk
  19299.         subclassOf: self 
  19300.         instanceVariableNames: f
  19301.         variable: true 
  19302.         words: true 
  19303.         pointers: false
  19304.         classVariableNames: d 
  19305.         poolDictionaries: s 
  19306.         category: cat 
  19307.         comment: nil
  19308.         changed: false! !
  19309.  
  19310.  
  19311. !Class methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 09:58'!
  19312. fileOut
  19313.     "Create a file whose name is the name of the receiver with '.st' as the 
  19314.     extension, and file a description of the receiver onto it."
  19315.     ^ self fileOutAsHtml: false! !
  19316.  
  19317. !Class methodsFor: 'fileIn/Out' stamp: 'jm 3/27/98 08:31'!
  19318. fileOutAsHtml: useHtml
  19319.     "File a description of the receiver onto a new file whose base name is the name of the receiver."
  19320.  
  19321.     | fileStream |
  19322.     fileStream _ useHtml
  19323.         ifTrue: [(FileStream newFileNamed: self name, FileDirectory dot, 'html') asHtml]
  19324.         ifFalse: [FileStream newFileNamed: self name, FileDirectory dot, 'st'].
  19325.     fileStream header; timeStamp.
  19326.     self sharedPools size > 0 ifTrue: [
  19327.         self shouldFileOutPools
  19328.             ifTrue: [self fileOutSharedPoolsOn: fileStream]].
  19329.     self fileOutOn: fileStream moveSource: false toFile: 0.
  19330.     fileStream trailer; close.
  19331. ! !
  19332.  
  19333. !Class methodsFor: 'fileIn/Out'!
  19334. fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex 
  19335.     "File a description of the receiver on aFileStream. If the boolean argument,
  19336.     moveSource, is true, then set the trailing bytes to the position of aFileStream and
  19337.     to fileIndex in order to indicate where to find the source code."
  19338.  
  19339.     Transcript cr; show: name.
  19340.     super
  19341.         fileOutOn: aFileStream
  19342.         moveSource: moveSource
  19343.         toFile: fileIndex.
  19344.     self class nonTrivial
  19345.         ifTrue:
  19346.             [aFileStream cr; nextPutAll: '"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!!'; cr; cr.
  19347.             self class
  19348.                 fileOutOn: aFileStream
  19349.                 moveSource: moveSource
  19350.                 toFile: fileIndex]! !
  19351.  
  19352. !Class methodsFor: 'fileIn/Out' stamp: 'ikp 1/3/98 22:45'!
  19353. fileOutPool: aPool onFileStream: aFileStream 
  19354.     | aPoolName aValue |
  19355.     aPoolName _ Smalltalk keyAtValue: aPool.
  19356.     Transcript cr; show: aPoolName.
  19357.     aFileStream nextPutAll: 'Transcript show: ''' , aPoolName , '''; cr!!'; cr.
  19358.     aFileStream nextPutAll: 'Smalltalk at: #' , aPoolName , ' put: Dictionary new!!'; cr.
  19359.     aPool keys asSortedCollection do: [ :aKey |
  19360.         aValue _ aPool at: aKey.
  19361.         aFileStream nextPutAll: aPoolName , ' at: #' , aKey asString , ' put:  '.
  19362.         (aValue isKindOf: Number)
  19363.             ifTrue: [aValue printOn: aFileStream]
  19364.             ifFalse: [aFileStream nextPutAll: '('.
  19365.                     aValue printOn: aFileStream.
  19366.                     aFileStream nextPutAll: ')'].
  19367.         aFileStream nextPutAll: '!!'; cr].
  19368.     aFileStream cr! !
  19369.  
  19370. !Class methodsFor: 'fileIn/Out'!
  19371. fileOutSharedPoolsOn: aFileStream
  19372.     "file out the shared pools of this class after prompting the user about each pool"
  19373.     | poolsToFileOut |
  19374.     poolsToFileOut _ self sharedPools select: 
  19375.         [:aPool | (self shouldFileOutPool: (Smalltalk keyAtValue: aPool))].
  19376.     poolsToFileOut do: [:aPool | self fileOutPool: aPool onFileStream: aFileStream].
  19377.     ! !
  19378.  
  19379. !Class methodsFor: 'fileIn/Out' stamp: 'tk 3/24/98 10:16'!
  19380. objectToStoreOnDataStream
  19381.     "I am about to be written on an object file.  Write a reference to a class in Smalltalk instead."
  19382.  
  19383.     ^ DiskProxy global: self theNonMetaClass name selector: #yourself
  19384.             args: (Array new)! !
  19385.  
  19386. !Class methodsFor: 'fileIn/Out'!
  19387. reformatAll 
  19388.     "Reformat all methods in this class.
  19389.     Leaves old code accessible to version browsing"
  19390.     super reformatAll.        "me..."
  19391.     self class reformatAll    "...and my metaclass"! !
  19392.  
  19393. !Class methodsFor: 'fileIn/Out'!
  19394. removeFromChanges
  19395.     "References to the receiver, a class, and its metaclass should no longer be included in the system ChangeSet.
  19396.     7/18/96 sw: call removeClassAndMetaClassChanges:"
  19397.  
  19398.     Smalltalk changes removeClassAndMetaClassChanges: self! !
  19399.  
  19400. !Class methodsFor: 'fileIn/Out'!
  19401. shouldFileOutPool: aPoolName
  19402.     "respond with true if the user wants to file out aPoolName"
  19403.     ^self confirm: ('FileOut the sharedPool ', aPoolName, '?')! !
  19404.  
  19405. !Class methodsFor: 'fileIn/Out'!
  19406. shouldFileOutPools
  19407.     "respond with true if the user wants to file out the shared pools"
  19408.     ^self confirm: 'FileOut selected sharedPools?'! !
  19409.  
  19410. !Class methodsFor: 'fileIn/Out' stamp: 'tk 3/26/98 10:18'!
  19411. storeDataOn: aDataStream
  19412.     "I don't get stored.  Use a DiskProxy"
  19413.  
  19414.     self error: 'use a DiskProxy to store a Class'! !
  19415.  
  19416. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  19417.  
  19418. Class class
  19419.     instanceVariableNames: ''!
  19420.  
  19421. !Class class methodsFor: 'instance creation'!
  19422. template: category 
  19423.     "Answer an expression that can be edited and evaluated in order to 
  19424.     define a new class."
  19425.  
  19426.     ^'Object subclass: #NameOfClass
  19427.     instanceVariableNames: ''instVarName1 instVarName2''
  19428.     classVariableNames: ''ClassVarName1 ClassVarName2''
  19429.     poolDictionaries: ''''
  19430.     category: ''' , category , ''''! !
  19431.  
  19432.  
  19433. !Class class methodsFor: 'fileIn/Out'!
  19434. fileOutPool: aString
  19435.     "file out the global pool named aString"
  19436.     | f |
  19437.     f _ FileStream newFileNamed: aString, '.st'.
  19438.     self new fileOutPool: (Smalltalk at: aString asSymbol) onFileStream: f.     f close.
  19439.     ! !
  19440. Object subclass: #ClassCategoryReader
  19441.     instanceVariableNames: 'class category changeStamp '
  19442.     classVariableNames: ''
  19443.     poolDictionaries: ''
  19444.     category: 'Kernel-Classes'!
  19445. !ClassCategoryReader commentStamp: 'di 5/22/1998 16:32' prior: 0!
  19446. ClassCategoryReader comment:
  19447. 'I represent a mechanism for retrieving class descriptions stored on a file.'!
  19448.  
  19449.  
  19450. !ClassCategoryReader methodsFor: 'fileIn/Out' stamp: 'tk 12/15/97 16:26'!
  19451. scanFrom: aStream 
  19452.     "File in methods from the stream, aStream."
  19453.     | methodText |
  19454.     [methodText _ aStream nextChunkText.
  19455.      methodText size > 0]
  19456.         whileTrue:
  19457.         [class compile: methodText classified: category
  19458.             withStamp: changeStamp
  19459.             notifying: (SyntaxError new category: category)]! !
  19460.  
  19461.  
  19462. !ClassCategoryReader methodsFor: 'private' stamp: '6/5/97 di'!
  19463. setClass: aClass category: aCategory
  19464.     ^ self setClass: aClass category: aCategory changeStamp: String new
  19465. ! !
  19466.  
  19467. !ClassCategoryReader methodsFor: 'private' stamp: '6/5/97 di'!
  19468. setClass: aClass category: aCategory changeStamp: aString
  19469.  
  19470.     class _ aClass.
  19471.     category _ aCategory.
  19472.     changeStamp _ aString
  19473. ! !
  19474. ClassCategoryReader subclass: #ClassCommentReader
  19475.     instanceVariableNames: ''
  19476.     classVariableNames: ''
  19477.     poolDictionaries: ''
  19478.     category: 'Kernel-Classes'!
  19479.  
  19480. !ClassCommentReader methodsFor: 'as yet unclassified' stamp: 'tk 12/15/97 15:56'!
  19481. scanFrom: aStream 
  19482.     "File in the class comment from aStream.  Not string-i-fied, just a text, exactly as it is in the browser.  Move to changes file."
  19483.  
  19484.     class theNonMetaClass classComment: (aStream nextChunkText).
  19485.         "Writes it on the disk and saves a RemoteString ref"! !
  19486. Behavior subclass: #ClassDescription
  19487.     instanceVariableNames: 'instanceVariables organization '
  19488.     classVariableNames: ''
  19489.     poolDictionaries: ''
  19490.     category: 'Kernel-Classes'!
  19491. !ClassDescription commentStamp: 'di 5/22/1998 16:32' prior: 0!
  19492. ClassDescription comment:
  19493. 'I add a number of facilities to basic Behavior:
  19494.     Named instance variables
  19495.     Category organization for methods
  19496.     The notion of a name of this class (implemented as subclass responsibility)
  19497.     The maintenance of a ChangeSet, and logging changes on a file
  19498.     Most of the mechanism for fileOut.
  19499.     
  19500. I am an abstract class, in particular, my facilities are intended for inheritance by two subclasses, Class and Metaclass.'!
  19501.  
  19502.  
  19503. !ClassDescription methodsFor: 'initialize-release'!
  19504. obsolete
  19505.     "Make the receiver obsolete."
  19506.  
  19507.     organization _ nil.
  19508.     super obsolete! !
  19509.  
  19510. !ClassDescription methodsFor: 'initialize-release' stamp: 'tk 3/19/98 10:18'!
  19511. subclassOf: newSuper oldClass: oldClass instanceVariableNames: newInstVarString variable: v words: w pointers: p ifBad: badBlock 
  19512.     "Basic initialization message for creating classes using the information 
  19513.     provided as arguments. Answer whether old instances will be 
  19514.     invalidated."
  19515.     | oldNames newNames usedNames invalid oldSuperMeta newInstVarArray oldSpec |
  19516.     oldNames _ self allInstVarNames.
  19517.     usedNames _ #(self super thisContext true false nil ) asSet.
  19518.     newInstVarArray _ Scanner new scanFieldNames: newInstVarString.
  19519.     newNames _ newSuper allInstVarNames , newInstVarArray.
  19520.     newNames size > 254 ifTrue:
  19521.         [self error: 'A class cannot have more than 254 instance variables'.
  19522.         ^ badBlock value].
  19523.     newNames do: 
  19524.         [:fieldName | 
  19525.         (usedNames includes: fieldName)
  19526.             ifTrue: 
  19527.                 [self error: fieldName , ' is reserved (maybe in a superclass)'.
  19528.                 ^ badBlock value].
  19529.         usedNames add: fieldName].
  19530.     (invalid _ superclass ~~ newSuper)
  19531.         ifTrue: 
  19532.             ["superclass changed"
  19533.             oldSuperMeta _ superclass class.
  19534.             superclass ifNotNil: [superclass removeSubclass: self.
  19535.                 "Object flushCache"        "done in removeSubclass"].
  19536.             superclass _ newSuper.
  19537.             superclass addSubclass: self.
  19538.             self class superclass == oldSuperMeta 
  19539.                 ifTrue: ["Only false when self is a metaclass"
  19540.                         self class superclass: newSuper class]].
  19541.     instanceVariables _ newInstVarArray size = 0 ifFalse: [newInstVarArray].
  19542.     invalid _ invalid | (newNames  ~= oldNames).   "field names changed"
  19543.     oldSpec _ self instSpec.
  19544.     self format: newNames size
  19545.         variable: v
  19546.         words: w
  19547.         pointers: p.
  19548.     invalid _ invalid | (self instSpec ~= oldSpec).  "format changed"
  19549.     ^invalid! !
  19550.  
  19551. !ClassDescription methodsFor: 'initialize-release'!
  19552. updateInstancesFrom: oldClass 
  19553.     "Recreate any existing instances of the argument, oldClass, as instances of 
  19554.     the receiver, which is a newly changed class. Permute variables as 
  19555.     necessary."
  19556.  
  19557.     | oldInstVarNames map variable new instSize oldInstances |
  19558.     oldClass someInstance == nil ifTrue: [^self].
  19559.     "no instances to convert"
  19560.     oldInstVarNames _ oldClass allInstVarNames.
  19561.     map _ 
  19562.         self allInstVarNames 
  19563.             collect: [:instVarName | oldInstVarNames indexOf: instVarName].
  19564.     variable _ self isVariable.
  19565.     instSize _ self instSize.
  19566.  
  19567.     "Now perform a bulk mutation of old instances into new ones"
  19568.     oldInstances _ oldClass allInstances asArray.
  19569.     oldInstances elementsExchangeIdentityWith:
  19570.         (oldInstances collect: 
  19571.         [:old | 
  19572.         variable
  19573.             ifTrue: [new _ self basicNew: old basicSize]
  19574.             ifFalse: [new _ self basicNew].
  19575.         1 to: instSize do: 
  19576.             [:offset |  (map at: offset) > 0 ifTrue:
  19577.                 [new instVarAt: offset
  19578.                         put: (old instVarAt: (map at: offset))]].
  19579.         variable 
  19580.             ifTrue: [1 to: old basicSize do: 
  19581.                         [:offset |
  19582.                         new basicAt: offset put: (old basicAt: offset)]].
  19583.         new])! !
  19584.  
  19585. !ClassDescription methodsFor: 'initialize-release'!
  19586. validateFrom: oldClass in: environ instanceVariableNames: invalidFields methods: invalidMethods 
  19587.     "Recompile the receiver, a class, and redefine its subclasses if necessary.
  19588.     The parameter invalidFields is no longer really used"
  19589.  
  19590.     | newSub invalidSubMethods |
  19591.     oldClass becomeUncompact.  "Its about to be abandoned"
  19592.     invalidMethods & self hasMethods
  19593.         ifTrue: 
  19594.             [Transcript show: 'recompiling ' , self name , '...'.
  19595.             self compileAllFrom: oldClass.
  19596.             Transcript show: ' done'; cr].
  19597.     invalidSubMethods _ invalidMethods | (self instSize ~= oldClass instSize).
  19598.     self == oldClass
  19599.         ifTrue: [invalidSubMethods ifFalse: [^self]]
  19600.         ifFalse: [self updateInstancesFrom: oldClass].
  19601.     oldClass subclasses do: 
  19602.         [:sub | 
  19603.         newSub _ sub copyForValidation.
  19604.         newSub
  19605.             subclassOf: self
  19606.             oldClass: sub
  19607.             instanceVariableNames: sub instVarNames
  19608.             variable: sub isVariable
  19609.             words: sub isBytes not
  19610.             pointers: sub isBits not
  19611.             ifBad: [self error: 'terrible problem in recompiling subclasses!!'].
  19612.         newSub
  19613.             validateFrom: sub
  19614.             in: environ
  19615.             instanceVariableNames: invalidFields
  19616.             methods: invalidSubMethods]! !
  19617.  
  19618.  
  19619. !ClassDescription methodsFor: 'accessing'!
  19620. classVersion
  19621.     "Default.  Any class may return a later version to inform readers that use ReferenceStream.  8/17/96 tk"
  19622.     ^ 0! !
  19623.  
  19624. !ClassDescription methodsFor: 'accessing' stamp: 'tk 12/13/97 14:33'!
  19625. comment
  19626.     "Answer the receiver's comment. (If old format, not a Text, unpack the old way.) "
  19627.  
  19628.     | aString |
  19629.     aString _ self theNonMetaClass organization classComment.
  19630.     (aString asString beginsWith: self name, ' comment:\''' withCRs) 
  19631.         ifFalse: [^ self theNonMetaClass organization classComment]
  19632.         ifTrue: ["old format"
  19633.             aString size = 0 ifTrue: [^''].
  19634.             "get string only of classComment, undoubling quotes"
  19635.             ^ String readFromString: aString]! !
  19636.  
  19637. !ClassDescription methodsFor: 'accessing' stamp: 'tk 12/16/97 07:49'!
  19638. comment: aStringOrText
  19639.     "Set the receiver's comment to be the argument, aStringOrText."
  19640.  
  19641.     self theNonMetaClass classComment: aStringOrText.
  19642.     Smalltalk changes commentClass: self! !
  19643.  
  19644. !ClassDescription methodsFor: 'accessing'!
  19645. isMeta
  19646.     ^ false! !
  19647.  
  19648. !ClassDescription methodsFor: 'accessing'!
  19649. name
  19650.     "Answer a String that is the name of the receiver."
  19651.  
  19652.     self subclassResponsibility! !
  19653.  
  19654. !ClassDescription methodsFor: 'accessing'!
  19655. theNonMetaClass
  19656.     "Sent to a class or metaclass, always return the class"
  19657.  
  19658.     ^self! !
  19659.  
  19660.  
  19661. !ClassDescription methodsFor: 'copying'!
  19662. copy: sel from: class 
  19663.     "Install the method associated with the first argument, sel, a message 
  19664.     selector, found in the method dictionary of the second argument, class, 
  19665.     as one of the receiver's methods. Classify the message under -As yet not 
  19666.     classified-."
  19667.  
  19668.     self copy: sel
  19669.         from: class
  19670.         classified: nil! !
  19671.  
  19672. !ClassDescription methodsFor: 'copying'!
  19673. copy: sel from: class classified: cat 
  19674.     "Install the method associated with the first arugment, sel, a message 
  19675.     selector, found in the method dictionary of the second argument, class, 
  19676.     as one of the receiver's methods. Classify the message under the third 
  19677.     argument, cat."
  19678.  
  19679.     | code category |
  19680.     "Useful when modifying an existing class"
  19681.     code _ class sourceMethodAt: sel.
  19682.     code == nil
  19683.         ifFalse: 
  19684.             [cat == nil
  19685.                 ifTrue: [category _ class organization categoryOfElement: sel]
  19686.                 ifFalse: [category _ cat].
  19687.             (methodDict includesKey: sel)
  19688.                 ifTrue: [code asString = (self sourceMethodAt: sel) asString 
  19689.                             ifFalse: [self error: self name 
  19690.                                         , ' ' 
  19691.                                         , sel 
  19692.                                         , ' will be redefined if you proceed.']].
  19693.             self compile: code classified: category]! !
  19694.  
  19695. !ClassDescription methodsFor: 'copying'!
  19696. copyAll: selArray from: class 
  19697.     "Install all the methods found in the method dictionary of the second 
  19698.     argument, class, as the receiver's methods. Classify the messages under 
  19699.     -As yet not classified-."
  19700.  
  19701.     self copyAll: selArray
  19702.         from: class
  19703.         classified: nil! !
  19704.  
  19705. !ClassDescription methodsFor: 'copying'!
  19706. copyAll: selArray from: class classified: cat 
  19707.     "Install all the methods found in the method dictionary of the second 
  19708.     argument, class, as the receiver's methods. Classify the messages under 
  19709.     the third argument, cat."
  19710.  
  19711.     selArray do: 
  19712.         [:s | self copy: s
  19713.                 from: class
  19714.                 classified: cat]! !
  19715.  
  19716. !ClassDescription methodsFor: 'copying'!
  19717. copyAllCategoriesFrom: aClass 
  19718.     "Specify that the categories of messages for the receiver include all of 
  19719.     those found in the class, aClass. Install each of the messages found in 
  19720.     these categories into the method dictionary of the receiver, classified 
  19721.     under the appropriate categories."
  19722.  
  19723.     aClass organization categories do: [:cat | self copyCategory: cat from: aClass]! !
  19724.  
  19725. !ClassDescription methodsFor: 'copying'!
  19726. copyCategory: cat from: class 
  19727.     "Specify that one of the categories of messages for the receiver is cat, as 
  19728.     found in the class, class. Copy each message found in this category."
  19729.  
  19730.     self copyCategory: cat
  19731.         from: class
  19732.         classified: cat! !
  19733.  
  19734. !ClassDescription methodsFor: 'copying'!
  19735. copyCategory: cat from: aClass classified: newCat 
  19736.     "Specify that one of the categories of messages for the receiver is the 
  19737.     third argument, newCat. Copy each message found in the category cat in 
  19738.     class aClass into this new category."
  19739.  
  19740.     self copyAll: (aClass organization listAtCategoryNamed: cat)
  19741.         from: aClass
  19742.         classified: newCat! !
  19743.  
  19744.  
  19745. !ClassDescription methodsFor: 'printing'!
  19746. classVariablesString
  19747.     "Answer a string of my class variable names separated by spaces."
  19748.     | aStream |
  19749.     aStream _ WriteStream on: (String new: 100).
  19750.     self classPool keys asSortedCollection do: [:key | aStream nextPutAll: key; space].
  19751.     ^aStream contents! !
  19752.  
  19753. !ClassDescription methodsFor: 'printing'!
  19754. instanceVariablesString
  19755.     "Answer a string of my instance variable names separated by spaces."
  19756.  
  19757.     | aStream names |
  19758.     aStream _ WriteStream on: (String new: 100).
  19759.     names _ self instVarNames.
  19760.     1 to: names size do: [:i | aStream nextPutAll: (names at: i); space].
  19761.     ^aStream contents! !
  19762.  
  19763. !ClassDescription methodsFor: 'printing'!
  19764. printOn: aStream 
  19765.  
  19766.     aStream nextPutAll: self name! !
  19767.  
  19768. !ClassDescription methodsFor: 'printing'!
  19769. sharedPoolsString
  19770.     "Answer a string of my shared pool names separated by spaces."
  19771.  
  19772.     | aStream |
  19773.     aStream _ WriteStream on: (String new: 100).
  19774.     self sharedPools do: [:x | aStream nextPutAll: (Smalltalk keyAtValue: x ifAbsent: ['private']); space].
  19775.     ^ aStream contents! !
  19776.  
  19777. !ClassDescription methodsFor: 'printing'!
  19778. storeOn: aStream
  19779.     "Classes and Metaclasses have global names."
  19780.  
  19781.     aStream nextPutAll: self name! !
  19782.  
  19783.  
  19784. !ClassDescription methodsFor: 'instance variables'!
  19785. addInstVarName: aString 
  19786.     "Add the argument, aString, as one of the receiver's instance variables."
  19787.  
  19788.     self subclassResponsibility! !
  19789.  
  19790. !ClassDescription methodsFor: 'instance variables'!
  19791. browseClassVariables
  19792.     "Put up a browser showing the receiver's class variables.  2/1/96 sw"
  19793.  
  19794.     self classPool inspectWithLabel: 'Class Variables in ', self name! !
  19795.  
  19796. !ClassDescription methodsFor: 'instance variables'!
  19797. browseClassVarRefs 
  19798.     "1/17/96 sw: moved here from Browser so that it could be used from a variety of places."
  19799.  
  19800.     | lines labelStream vars allVars index owningClasses |
  19801.  
  19802.     lines _ OrderedCollection new.
  19803.     allVars _ OrderedCollection new.
  19804.     owningClasses _ OrderedCollection new.
  19805.     labelStream _ WriteStream on: (String new: 200).
  19806.     self withAllSuperclasses reverseDo:
  19807.         [:class |
  19808.         vars _ class classVarNames asSortedCollection.
  19809.         vars do:
  19810.             [:var |
  19811.             labelStream nextPutAll: var; cr.
  19812.             allVars add: var.
  19813.             owningClasses add: class].
  19814.         vars isEmpty ifFalse: [lines add: allVars size]].
  19815.     labelStream skip: -1 "cut last CR".
  19816.     index _ (PopUpMenu labels: labelStream contents lines: lines) startUp.
  19817.     index = 0 ifTrue: [^ self].
  19818.     Smalltalk browseAllCallsOn:
  19819.         ((owningClasses at: index) classPool associationAt: (allVars at: index))! !
  19820.  
  19821. !ClassDescription methodsFor: 'instance variables'!
  19822. browseInstVarDefs 
  19823.     "Copied from browseInstVarRefs.  Should be consolidated some day. 7/29/96 di
  19824.     7/30/96 sw: did the consolidation"
  19825.  
  19826.     self chooseInstVarThenDo:    
  19827.         [:aVar | self browseAllStoresInto: aVar]! !
  19828.  
  19829. !ClassDescription methodsFor: 'instance variables'!
  19830. browseInstVarRefs 
  19831.     "1/16/96 sw: moved here from Browser so that it could be used from a variety of places.
  19832.      7/30/96 sw: call chooseInstVarThenDo: to get the inst var choice"
  19833.  
  19834.     self chooseInstVarThenDo: 
  19835.         [:aVar | self browseAllAccessesTo: aVar]! !
  19836.  
  19837. !ClassDescription methodsFor: 'instance variables' stamp: 'sw 7/29/97 18:34'!
  19838. chooseInstVarThenDo: aBlock 
  19839.     "Put up a menu of all the instance variables in the receiver, and when the user chooses one, evaluate aBlock with the chosen variable as its parameter.  7/30/96 sw"
  19840.  
  19841.     | lines labelStream vars allVars index |
  19842.  
  19843.     lines _ OrderedCollection new.
  19844.     allVars _ OrderedCollection new.
  19845.     labelStream _ WriteStream on: (String new: 200).
  19846.     self withAllSuperclasses reverseDo:
  19847.         [:class |
  19848.         vars _ class instVarNames.
  19849.         vars do:
  19850.             [:var |
  19851.             labelStream nextPutAll: var; cr.
  19852.             allVars add: var].
  19853.         vars isEmpty ifFalse: [lines add: allVars size]].
  19854.     labelStream isEmpty ifTrue:
  19855.         [^ (PopUpMenu labels: ' OK ')
  19856.             startUpWithCaption: 'There are no
  19857. instance variables.'].
  19858.     labelStream skip: -1 "cut last CR".
  19859.     index _ (PopUpMenu labels: labelStream contents lines: lines) startUpWithCaption: 'Instance variables in
  19860. ', class name.
  19861.     index = 0 ifTrue: [^ self].
  19862.     aBlock value: (allVars at: index)! !
  19863.  
  19864. !ClassDescription methodsFor: 'instance variables'!
  19865. forceNewFrom: anArray
  19866.     "Create a new instance of the class and fill
  19867.     its instance variables up with the array."
  19868.     | object max |
  19869.  
  19870.     object _ self new.
  19871.     max _ self instSize.
  19872.     anArray doWithIndex: [:each :index |
  19873.         index > max ifFalse:
  19874.             [object instVarAt: index put: each]].
  19875.     ^ object! !
  19876.  
  19877. !ClassDescription methodsFor: 'instance variables'!
  19878. instVarNames
  19879.     "Answer an Array of the receiver's instance variable names."
  19880.  
  19881.     instanceVariables == nil
  19882.         ifTrue: [^#()]
  19883.         ifFalse: [^instanceVariables]! !
  19884.  
  19885. !ClassDescription methodsFor: 'instance variables'!
  19886. removeInstVarName: aString 
  19887.     "Remove the argument, aString, as one of the receiver's instance 
  19888.     variables. Create an error notification if the argument is not found."
  19889.  
  19890.     self subclassResponsibility! !
  19891.  
  19892. !ClassDescription methodsFor: 'instance variables' stamp: 'di 7/15/97 00:04'!
  19893. renameInstVar: oldName to: newName
  19894.     | i oldCode newCode parser header body sels |
  19895.     (i _ instanceVariables indexOf: oldName) = 0 ifTrue:
  19896.         [self error: oldName , ' is not defined in ', self name].
  19897.     self allSuperclasses , self withAllSubclasses asOrderedCollection do:
  19898.         [:cls | (cls instVarNames includes: newName) ifTrue:
  19899.             [self error: newName , ' is already used in ', cls name]].
  19900.     (self confirm: 'WARNING: Renaming of instance variables
  19901. is subject to substitution ambiguities.
  19902. Do you still wish to attempt it?') ifFalse: [self halt].
  19903.  
  19904.     "...In other words, this does a dumb text search-and-replace,
  19905.     which might improperly alter, eg, a literal string.  As long as
  19906.     the oldName is unique, everything should work jes' fine. - di"
  19907.     instanceVariables replaceFrom: i to: i with: (Array with: newName).
  19908.     self withAllSubclasses do:
  19909.         [:cls | sels _ cls selectors.
  19910.         sels removeAllFoundIn: #(DoIt DoItIn:).
  19911.         sels do:
  19912.             [:sel |
  19913.             oldCode _ cls sourceCodeAt: sel.
  19914.             "Don't make changes in the method header"
  19915.             (parser _ cls parserClass new) parseSelector: oldCode.
  19916.             header _ oldCode copyFrom: 1 to: (parser endOfLastToken min: oldCode size).
  19917.             body _ header size > oldCode size
  19918.                     ifTrue: ['']
  19919.                     ifFalse: [oldCode copyFrom: header size+1 to: oldCode size].
  19920.             newCode _ header , (body copyReplaceTokens: oldName with: newName).
  19921.             newCode ~= oldCode ifTrue:
  19922.                 [cls compile: newCode
  19923.                     classified: (cls organization categoryOfElement: sel)
  19924.                     notifying: nil]].
  19925.             cls isMeta ifFalse:
  19926.                 [oldCode _ cls comment.
  19927.                 newCode _ oldCode copyReplaceTokens: oldName with: newName.
  19928.                 newCode ~= oldCode ifTrue:
  19929.                     [cls comment: newCode]]]! !
  19930.  
  19931.  
  19932. !ClassDescription methodsFor: 'method dictionary'!
  19933. removeCategory: aString 
  19934.     "Remove each of the messages categorized under aString in the method 
  19935.     dictionary of the receiver. Then remove the category aString."
  19936.     | categoryName |
  19937.     categoryName _ aString asSymbol.
  19938.     (self organization listAtCategoryNamed: categoryName) do:
  19939.         [:sel | self removeSelector: sel].
  19940.     self organization removeCategory: categoryName! !
  19941.  
  19942. !ClassDescription methodsFor: 'method dictionary' stamp: 'sw 2/28/98 22:02'!
  19943. removeSelector: aSymbol 
  19944.     "Remove the message whose selector is aSymbol from the method 
  19945.     dictionary of the receiver, if it is there. Answer nil otherwise."
  19946.  
  19947.     (methodDict includesKey: aSymbol) ifFalse: [^nil].
  19948.     self wantsChangeSetLogging ifTrue:
  19949.         [Smalltalk changes removeSelector: aSymbol class: self].
  19950.     super removeSelector: aSymbol.
  19951.     self organization removeElement: aSymbol.
  19952.     self acceptsLoggingOfCompilation ifTrue:
  19953.         [Smalltalk logChange: self name , ' removeSelector: #' , aSymbol]! !
  19954.  
  19955.  
  19956. !ClassDescription methodsFor: 'organization'!
  19957. category
  19958.     "Answer the system organization category for the receiver."
  19959.  
  19960.     ^SystemOrganization categoryOfElement: self name! !
  19961.  
  19962. !ClassDescription methodsFor: 'organization'!
  19963. category: cat 
  19964.     "Categorize the receiver under the system category, cat, removing it from 
  19965.     any previous categorization."
  19966.  
  19967.     (cat isKindOf: String)
  19968.         ifTrue: [SystemOrganization classify: self name under: cat asSymbol]
  19969.         ifFalse: [self errorCategoryName]! !
  19970.  
  19971. !ClassDescription methodsFor: 'organization'!
  19972. organization
  19973.     "Answer the instance of ClassOrganizer that represents the organization 
  19974.     of the messages of the receiver."
  19975.  
  19976.     organization==nil
  19977.         ifTrue: [organization _ 
  19978.                  ClassOrganizer defaultList: 
  19979.                         methodDict keys asSortedCollection asArray].
  19980.     ^organization! !
  19981.  
  19982. !ClassDescription methodsFor: 'organization' stamp: 'di 7/17/97 00:06'!
  19983. whichCategoryIncludesSelector: aSelector 
  19984.     "Answer the category of the argument, aSelector, in the organization of 
  19985.     the receiver, or answer nil if the receiver does not inlcude this selector."
  19986.  
  19987.     (self includesSelector: aSelector)
  19988.         ifTrue: [^ self organization categoryOfElement: aSelector]
  19989.         ifFalse: [^nil]! !
  19990.  
  19991. !ClassDescription methodsFor: 'organization'!
  19992. zapOrganization
  19993.     "Remove the organization of this class by message categories.
  19994.     This is typically done to save space in small systems.  Classes and methods
  19995.     created or filed in subsequently will, nonetheless, be organized"
  19996.  
  19997.     organization _ nil.
  19998.     self isMeta ifFalse: [self class zapOrganization]! !
  19999.  
  20000.  
  20001. !ClassDescription methodsFor: 'compiling'!
  20002. acceptsLoggingOfCompilation
  20003.     "weird name is so that it will come lexically before #compile, so that a clean build can make it through.  7/7/96 sw"
  20004.  
  20005.     ^ true! !
  20006.  
  20007. !ClassDescription methodsFor: 'compiling'!
  20008. compile: code classified: heading 
  20009.     "Compile the argument, code, as source code in the context of the 
  20010.     receiver and install the result in the receiver's method dictionary under 
  20011.     the classification indicated by the second argument, heading. nil is to be 
  20012.     notified if an error occurs. The argument code is either a string or an 
  20013.     object that converts to a string or a PositionableStream on an object that 
  20014.     converts to a string."
  20015.  
  20016.     ^self
  20017.         compile: code
  20018.         classified: heading
  20019.         notifying: (SyntaxError new category: heading)! !
  20020.  
  20021. !ClassDescription methodsFor: 'compiling' stamp: 'sw 8/21/97 00:26'!
  20022. compile: text classified: category notifying: requestor
  20023.     | stamp |
  20024.     stamp _ self acceptsLoggingOfCompilation ifTrue: [Utilities changeStamp] ifFalse: [nil].
  20025.     ^ self compile: text classified: category
  20026.         withStamp: stamp notifying: requestor
  20027.  
  20028.  ! !
  20029.  
  20030. !ClassDescription methodsFor: 'compiling' stamp: 'di 2/2/98 12:51'!
  20031. compile: text classified: category withStamp: changeStamp notifying: requestor 
  20032.     | selector priorMethod method methodNode newText |
  20033.     method _ self
  20034.         compile: text asString
  20035.         notifying: requestor
  20036.         trailer: #(0 0 0 0)
  20037.         ifFail: [^nil]
  20038.         elseSetSelectorAndNode: 
  20039.             [:sel :node | selector _ sel.
  20040.             priorMethod _ methodDict at: selector ifAbsent: [nil].
  20041.             methodNode _ node].
  20042.     self acceptsLoggingOfCompilation ifTrue:
  20043.         [newText _ (requestor ~~ nil and: [Preferences confirmFirstUseOfStyle])
  20044.             ifTrue: [text askIfAddStyle: priorMethod req: requestor]
  20045.             ifFalse: [text].
  20046.          method putSource: newText
  20047.                 fromParseNode: methodNode
  20048.                 class: self category: category withStamp: changeStamp 
  20049.                 inFile: 2 priorMethod: priorMethod].
  20050.     self organization classify: selector under: category.
  20051.     ^selector! !
  20052.  
  20053. !ClassDescription methodsFor: 'compiling'!
  20054. compile: code notifying: requestor 
  20055.     "Refer to the comment in Behavior|compile:notifying:." 
  20056.  
  20057.     ^self compile: code
  20058.          classified: ClassOrganizer default
  20059.          notifying: requestor! !
  20060.  
  20061. !ClassDescription methodsFor: 'compiling'!
  20062. compile: code notifying: requestor trailer: bytes
  20063.         ifFail: failBlock
  20064.         elseSetSelectorAndNode: selAndNodeBlock
  20065.     "Intercept this message in order to remember system changes.
  20066.      5/15/96 sw: modified so that if the class does not wish its methods logged in the changes file, then they also won't be accumulated in the current change set.
  20067.     7/12/96 sw: use wantsChangeSetLogging to determine whether to put in change set"
  20068.  
  20069.     | methodNode selector method |
  20070.     methodNode _ self compilerClass new
  20071.                 compile: code
  20072.                 in: self
  20073.                 notifying: requestor
  20074.                 ifFail: failBlock.
  20075.     selector _ methodNode selector.
  20076.     selAndNodeBlock value: selector value: methodNode.
  20077.     self wantsChangeSetLogging ifTrue:
  20078.         [(methodDict includesKey: selector)
  20079.             ifTrue: [Smalltalk changes changeSelector: selector class: self]
  20080.             ifFalse: [Smalltalk changes addSelector: selector class: self]].
  20081.     methodNode encoder requestor: requestor.  "Why was this not preserved?"
  20082.     method _ methodNode generate: bytes.
  20083.     self addSelector: selector withMethod: method.
  20084.     ^ method! !
  20085.  
  20086. !ClassDescription methodsFor: 'compiling'!
  20087. wantsChangeSetLogging
  20088.     "Answer whether code submitted for the receiver should be remembered by the changeSet mechanism.  7/12/96 sw"
  20089.  
  20090.  
  20091.     ^ true! !
  20092.  
  20093.  
  20094. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 12/29/97 13:11'!
  20095. classComment: aString
  20096.     "Store the comment, aString or Text or RemoteString, associated with the class we are orgainzing.  Empty string gets stored only if had a non-empty one before."
  20097.  
  20098.     | ptr header file oldCommentRemoteStr |
  20099.     (aString isKindOf: RemoteString) ifTrue: [^ organization classComment: aString].
  20100.     oldCommentRemoteStr _ organization commentRemoteStr.
  20101.     (aString size = 0) & (oldCommentRemoteStr == nil) ifTrue: [^ organization classComment: nil].
  20102.         "never had a class comment, no need to write empty string out"
  20103.  
  20104.     ptr _ oldCommentRemoteStr ifNil: [0] ifNotNil: [oldCommentRemoteStr sourcePointer].
  20105.     SourceFiles ifNotNil: [(file _ SourceFiles at: 2) ifNotNil: [
  20106.         file setToEnd; cr; nextPut: $!!.    "directly"
  20107.         "Should be saying (file command: 'H3') for HTML, but ignoring it here"
  20108.         header _ String streamContents: [:strm | strm nextPutAll: self name;
  20109.             nextPutAll: ' commentStamp: '.
  20110.             Utilities changeStamp storeOn: strm.
  20111.             strm nextPutAll: ' prior: '; nextPutAll: ptr printString].
  20112.         file nextChunkPut: header]].
  20113.     organization classComment: (RemoteString newString: aString onFileNumber: 2).
  20114.     Smalltalk changes commentClass: self.    ! !
  20115.  
  20116. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 12/13/97 14:20'!
  20117. commentFollows 
  20118.     "Answer a ClassCommentReader who will scan in the comment."
  20119.  
  20120.     ^ ClassCommentReader new setClass: self category: #Comment
  20121.  
  20122.     "False commentFollows inspect"! !
  20123.  
  20124. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 12/13/97 14:21'!
  20125. commentStamp: changeStamp prior: indexAndOffset
  20126.     "Prior source link ignored when filing in."
  20127.  
  20128.     ^ ClassCommentReader new setClass: self
  20129.                 category: #Comment
  20130.                 changeStamp: changeStamp
  20131. ! !
  20132.  
  20133. !ClassDescription methodsFor: 'fileIn/Out'!
  20134. definition
  20135.     "Answer a String that defines the receiver."
  20136.  
  20137.     | aStream |
  20138.     aStream _ WriteStream on: (String new: 300).
  20139.     aStream nextPutAll: 
  20140.         (superclass == nil
  20141.             ifTrue: ['nil']
  20142.             ifFalse: [superclass name])
  20143.         , self kindOfSubclass.
  20144.     self name storeOn: aStream.
  20145.     aStream cr; tab; nextPutAll: 'instanceVariableNames: '.
  20146.     aStream store: self instanceVariablesString.
  20147.     aStream cr; tab; nextPutAll: 'classVariableNames: '.
  20148.     aStream store: self classVariablesString.
  20149.     aStream cr; tab; nextPutAll: 'poolDictionaries: '.
  20150.     aStream store: self sharedPoolsString.
  20151.     aStream cr; tab; nextPutAll: 'category: '.
  20152.     (SystemOrganization categoryOfElement: self name) asString storeOn: aStream.
  20153.     ^aStream contents! !
  20154.  
  20155. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 10:06'!
  20156. fileOutCategory: catName 
  20157.     ^ self fileOutCategory: catName asHtml: false! !
  20158.  
  20159. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 10:05'!
  20160. fileOutCategory: catName asHtml: useHtml
  20161.     "FileOut the named category, possibly in Html format."
  20162.     | fileStream |
  20163.     fileStream _ useHtml
  20164.         ifTrue: [(FileStream newFileNamed: self name , '-' , catName , '.html') asHtml]
  20165.         ifFalse: [FileStream newFileNamed: self name , '-' , catName , '.st'].
  20166.     fileStream header; timeStamp.
  20167.     self fileOutCategory: catName on: fileStream moveSource: false toFile: 0.
  20168.     fileStream trailer; close! !
  20169.  
  20170. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 5/17/1998 10:40'!
  20171. fileOutCategory: aString on: aFileStream moveSource: moveSource toFile: fileIndex 
  20172.     "File a description of the receiver's category, aString, onto aFileStream. If 
  20173.     moveSource, is true, then set the method source pointer to the new file position.
  20174.     Note when this method is called with moveSource=true, it is condensing the
  20175.     .sources file, and should only write one preamble per method category."
  20176.  
  20177.     aFileStream cr.
  20178.  
  20179. true ifTrue:
  20180.     ["Overridden to preserve author stamps in sources file regardless"
  20181.     (self organization listAtCategoryNamed: aString)
  20182.         do: [:sel | self printMethodChunk: sel withPreamble: true
  20183.                         on: aFileStream moveSource: moveSource toFile: fileIndex].
  20184.     ^ self].
  20185.  
  20186.     moveSource ifTrue:
  20187.         ["Single header for condensing source files"
  20188.         self printCategoryChunk: aString on: aFileStream].
  20189.     (self organization listAtCategoryNamed: aString)
  20190.         do: [:sel | self printMethodChunk: sel withPreamble: moveSource not
  20191.                         on: aFileStream moveSource: moveSource toFile: fileIndex].
  20192.     moveSource ifTrue: [aFileStream nextChunkPut: ' ']! !
  20193.  
  20194. !ClassDescription methodsFor: 'fileIn/Out'!
  20195. fileOutChangedMessages: aSet on: aFileStream 
  20196.     "File a description of the messages of the receiver that have been 
  20197.     changed (i.e., are entered into the argument, aSet) onto aFileStream."
  20198.  
  20199.     self fileOutChangedMessages: aSet
  20200.         on: aFileStream
  20201.         moveSource: false
  20202.         toFile: 0! !
  20203.  
  20204. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/26/97 21:41'!
  20205. fileOutChangedMessages: aSet on: aFileStream moveSource: moveSource toFile: fileIndex 
  20206.     "File a description of the messages of this class that have been 
  20207.     changed (i.e., are entered into the argument, aSet) onto aFileStream.  If 
  20208.     moveSource, is true, then set the method source pointer to the new file position.
  20209.     Note when this method is called with moveSource=true, it is condensing the
  20210.     .changes file, and should only write a preamble for every method."
  20211.     | org sels |
  20212.     (org _ self organization) categories do: 
  20213.         [:cat | 
  20214.         sels _ (org listAtCategoryNamed: cat) select: [:sel | aSet includes: sel].
  20215.         sels do:
  20216.             [:sel |  self printMethodChunk: sel withPreamble: true on: aFileStream
  20217.                             moveSource: moveSource toFile: fileIndex]]! !
  20218.  
  20219. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 15:52'!
  20220. fileOutMethod: selector
  20221.     "Write source code of a single method on a file.  Make up a name for the file."
  20222.     self fileOutMethod: selector asHtml: false! !
  20223.  
  20224. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 15:51'!
  20225. fileOutMethod: selector asHtml: useHtml
  20226.     "Write source code of a single method on a file in .st or .html format"
  20227.     | fileStream nameBody |
  20228.     (self includesSelector: selector) ifFalse: [^ self halt: 'Selector not found'].
  20229.     nameBody _ self name , '-' , (selector copyReplaceAll: ':' with: '').
  20230.     fileStream _ useHtml
  20231.         ifTrue: [(FileStream newFileNamed: nameBody , '.html') asHtml]
  20232.         ifFalse: [FileStream newFileNamed: nameBody , '.st'].
  20233.     fileStream header; timeStamp.
  20234.     self printMethodChunk: selector withPreamble: true
  20235.         on: fileStream moveSource: false toFile: 0.
  20236.     fileStream close! !
  20237.  
  20238. !ClassDescription methodsFor: 'fileIn/Out'!
  20239. fileOutOn: aFileStream 
  20240.     "File a description of the receiver on aFileStream."
  20241.  
  20242.     self fileOutOn: aFileStream
  20243.         moveSource: false
  20244.         toFile: 0! !
  20245.  
  20246. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'sw 1/15/98 23:38'!
  20247. fileOutOn: aFileStream moveSource: moveSource toFile: fileIndex
  20248.     "File a description of the receiver on aFileStream. If the boolean 
  20249.     argument, moveSource, is true, then set the trailing bytes to the position 
  20250.     of aFileStream and to fileIndex in order to indicate where to find the 
  20251.     source code."
  20252.  
  20253.     aFileStream command: 'H3'.
  20254.         aFileStream nextChunkPut: self definition.
  20255.         aFileStream command: '/H3'.
  20256.  
  20257.     self organization
  20258.         putCommentOnFile: aFileStream
  20259.         numbered: fileIndex
  20260.         moveSource: moveSource
  20261.         forClass: self.
  20262.     self organization categories do: 
  20263.         [:heading |
  20264.         self fileOutCategory: heading
  20265.             on: aFileStream
  20266.             moveSource: moveSource
  20267.             toFile: fileIndex]! !
  20268.  
  20269. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/28/97 20:35'!
  20270. fileOutOrganizationOn: aFileStream
  20271.     "File a description of the receiver's organization on aFileStream."
  20272.  
  20273.     aFileStream cr; nextPut: $!!.
  20274.     aFileStream nextChunkPut: self name, ' reorganize'; cr.
  20275.     aFileStream nextChunkPut: self organization printString; cr! !
  20276.  
  20277. !ClassDescription methodsFor: 'fileIn/Out'!
  20278. kindOfSubclass
  20279.     "Answer a string that describes what kind of subclass the receiver is, i.e.,
  20280.     variable, variable byte, variable word, or not variable."
  20281.  
  20282.     self isVariable
  20283.         ifTrue: [self isBits
  20284.                     ifTrue: [self isBytes
  20285.                                 ifTrue: [^' variableByteSubclass: ']
  20286.                                 ifFalse: [^' variableWordSubclass: ']]
  20287.                     ifFalse: [^' variableSubclass: ']]
  20288.         ifFalse: [^' subclass: ']! !
  20289.  
  20290. !ClassDescription methodsFor: 'fileIn/Out' stamp: '6/5/97 di'!
  20291. methods
  20292.     "Answer a ClassCategoryReader for compiling messages that are not classified, as in fileouts made with Smalltalk/V"
  20293.  
  20294.     ^ ClassCategoryReader new setClass: self
  20295.                             category: 'as yet unclassified' asSymbol! !
  20296.  
  20297. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 12/29/97 13:00'!
  20298. methodsFor: categoryName 
  20299.     "Answer a ClassCategoryReader for compiling the messages in the category, categoryName, of the receiver."
  20300.  
  20301.     ^ ClassCategoryReader new setClass: self category: categoryName asSymbol
  20302.  
  20303.     "(False methodsFor: 'logical operations') inspect"! !
  20304.  
  20305. !ClassDescription methodsFor: 'fileIn/Out'!
  20306. methodsFor: aString priorSource: sourcePosition inFile: fileIndex
  20307.     "Prior source pointer ignored when filing in."
  20308.     ^ self methodsFor: aString! !
  20309.  
  20310. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/13/97 13:51'!
  20311. methodsFor: categoryName stamp: changeStamp 
  20312.     ^ self methodsFor: categoryName stamp: (Utilities fixStamp: changeStamp) prior: 0! !
  20313.  
  20314. !ClassDescription methodsFor: 'fileIn/Out' stamp: '6/5/97 di'!
  20315. methodsFor: categoryName stamp: changeStamp prior: indexAndOffset
  20316.     "Prior source link ignored when filing in."
  20317.     ^ ClassCategoryReader new setClass: self
  20318.                 category: categoryName asSymbol
  20319.                 changeStamp: changeStamp
  20320. ! !
  20321.  
  20322. !ClassDescription methodsFor: 'fileIn/Out'!
  20323. moveChangesTo: newFile 
  20324.     "Used in the process of condensing changes, this message requests that 
  20325.     the source code of all methods of the receiver that have been changed 
  20326.     should be moved to newFile."
  20327.  
  20328.     | changes |
  20329.     self organization moveChangedCommentToFile: newFile numbered: 2.
  20330.     changes _ methodDict keys select: [:sel | (methodDict at: sel) fileIndex > 1].
  20331.     self fileOutChangedMessages: changes
  20332.         on: newFile
  20333.         moveSource: true
  20334.         toFile: 2! !
  20335.  
  20336. !ClassDescription methodsFor: 'fileIn/Out' stamp: '6/5/97 di'!
  20337. printCategoryChunk: categoryName on: aFileStream
  20338.     ^ self printCategoryChunk: categoryName withStamp: '' on: aFileStream! !
  20339.  
  20340. !ClassDescription methodsFor: 'fileIn/Out' stamp: '6/5/97 di'!
  20341. printCategoryChunk: category on: aFileStream priorMethod: priorMethod
  20342.     ^ self printCategoryChunk: category on: aFileStream
  20343.         withStamp: Utilities changeStamp priorMethod: priorMethod! !
  20344.  
  20345. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'di 6/26/97 11:51'!
  20346. printCategoryChunk: category on: aFileStream withStamp: changeStamp priorMethod: priorMethod
  20347.     "Print a method category preamble.  This must have a category name.
  20348.     It may have an author/date stamp, and it may have a prior source link.
  20349.     If it has a prior source link, it MUST have a stamp, even if it is empty."
  20350.  
  20351. "The current design is that changeStamps and prior source links are preserved in the changes file.  All fileOuts include changeStamps.  Condensing sources, however, eliminates all stamps (and links, natch)."
  20352.  
  20353.     aFileStream cr; command: 'H3'; nextPut: $!!.
  20354.     aFileStream nextChunkPut: (String streamContents:
  20355.         [:strm |
  20356.         strm nextPutAll: self name; nextPutAll: ' methodsFor: '; print: category asString.
  20357.         (changeStamp size > 0 or: [priorMethod ~~ nil]) ifTrue:
  20358.             [strm nextPutAll: ' stamp: '; print: changeStamp].
  20359.         priorMethod ~~ nil ifTrue:
  20360.             [strm nextPutAll: ' prior: '; print: priorMethod sourcePointer]]).
  20361.     aFileStream command: '/H3'.! !
  20362.  
  20363. !ClassDescription methodsFor: 'fileIn/Out' stamp: '6/6/97 di'!
  20364. printCategoryChunk: categoryName withStamp: changeStamp on: aFileStream
  20365.     ^ self printCategoryChunk: categoryName on: aFileStream withStamp: changeStamp
  20366.         priorMethod: nil! !
  20367.  
  20368. !ClassDescription methodsFor: 'fileIn/Out' stamp: 'tk 12/15/97 15:01'!
  20369. printMethodChunk: selector withPreamble: doPreamble on: outStream
  20370.         moveSource: moveSource toFile: fileIndex
  20371.     "Copy the source code for the method associated with selector onto the fileStream.  If moveSource true, then also set the source code pointer of the method."
  20372.     | preamble method oldPos newPos sourceFile |
  20373.     doPreamble 
  20374.         ifTrue: [preamble _ self name , ' methodsFor: ' ,
  20375.                     (self organization categoryOfElement: selector) asString printString]
  20376.         ifFalse: [preamble _ ''].
  20377.     method _ methodDict at: selector.
  20378.     ((method fileIndex = 0
  20379.         or: [(SourceFiles at: method fileIndex) == nil])
  20380.         or: [(oldPos _ method filePosition) = 0])
  20381.         ifTrue:
  20382.         ["The source code is not accessible.  We must decompile..."
  20383.         preamble size > 0 ifTrue: [outStream cr; nextPut: $!!; nextChunkPut: preamble; cr].
  20384.         outStream nextChunkPut: (self decompilerClass new decompile: selector
  20385.                                             in: self method: method) decompileString]
  20386.         ifFalse:
  20387.         [sourceFile _ SourceFiles at: method fileIndex.
  20388.         sourceFile position: oldPos.
  20389.         preamble size > 0 ifTrue:    "Copy the preamble"
  20390.             [outStream copyPreamble: preamble from: sourceFile].
  20391.         "Copy the method chunk"
  20392.         newPos _ outStream position.
  20393.         outStream copyMethodChunkFrom: sourceFile.
  20394.         sourceFile skipSeparators.    "The following chunk may have ]style["
  20395.         sourceFile peek == $] ifTrue: [
  20396.             outStream cr; copyMethodChunkFrom: sourceFile].
  20397.         moveSource ifTrue:    "Set the new method source pointer"
  20398.             [method setSourcePosition: newPos inFile: fileIndex]].
  20399.     preamble size > 0 ifTrue: [outStream nextChunkPut: ' '].
  20400.     ^ outStream cr.
  20401. ! !
  20402.  
  20403. !ClassDescription methodsFor: 'fileIn/Out'!
  20404. reformatAll 
  20405.     "Reformat all methods in this class.
  20406.     Leaves old code accessible to version browsing"
  20407.     self selectorsDo: [:sel | self reformatMethodAt: sel]! !
  20408.  
  20409. !ClassDescription methodsFor: 'fileIn/Out'!
  20410. reformatMethodAt: selector 
  20411.     | newCodeString method | 
  20412.     newCodeString _ (self compilerClass new)
  20413.         format: (self sourceCodeAt: selector)
  20414.         in: self
  20415.         notifying: nil.
  20416.     method _ self compiledMethodAt: selector.
  20417.     method
  20418.         putSource: newCodeString
  20419.         fromParseNode: nil
  20420.         class: self
  20421.         category: (self organization categoryOfElement: selector)
  20422.         inFile: 2 priorMethod: method! !
  20423.  
  20424. !ClassDescription methodsFor: 'fileIn/Out'!
  20425. reorganize
  20426.     "Record that the receiver is being reorganized and answer the receiver's organization."
  20427.  
  20428.     Smalltalk changes reorganizeClass: self.
  20429.     ^self organization! !
  20430.  
  20431.  
  20432. !ClassDescription methodsFor: 'private'!
  20433. errorCategoryName
  20434.     self error: 'Category name must be a String'! !
  20435.  
  20436. !ClassDescription methodsFor: 'private' stamp: 'di 1/30/98 11:56'!
  20437. spaceUsed
  20438.     "Answer a rough estimate of number of bytes in this class and its metaclass"
  20439.     | space method |
  20440.     space _ 0.
  20441.     self selectorsDo:
  20442.         [:sel | space _ space + 16.  "dict and org'n space"
  20443.         method _ self compiledMethodAt: sel.
  20444.         space _ space + (method size + 6 "hdr + avg pad").
  20445.         method literals do:
  20446.             [:lit | ((lit isMemberOf: Symbol) or: [lit isMemberOf: SmallInteger]) ifFalse:
  20447.                 [(lit isMemberOf: String) ifTrue: [space _ space + (lit size+6)].
  20448.                 (lit isMemberOf: Array) ifTrue: [space _ space + (lit size+1*4)]]]].
  20449.     (self isMemberOf: Metaclass)
  20450.         ifTrue: [^ space]
  20451.         ifFalse: [^ space + self class spaceUsed]! !
  20452. Object subclass: #ClassOrganizer
  20453.     instanceVariableNames: 'globalComment categoryArray categoryStops elementArray '
  20454.     classVariableNames: 'Default NullCategory '
  20455.     poolDictionaries: ''
  20456.     category: 'Kernel-Classes'!
  20457. !ClassOrganizer commentStamp: 'di 5/22/1998 16:32' prior: 0!
  20458. ClassOrganizer comment:
  20459. 'I represent method categorization information for classes.'!
  20460.  
  20461.  
  20462. !ClassOrganizer methodsFor: 'accessing'!
  20463. categories
  20464.     "Answer an Array of categories (names)."
  20465.     (categoryArray size = 1 
  20466.         and: [categoryArray first = Default & (elementArray size = 0)])
  20467.         ifTrue: [^Array with: NullCategory].
  20468.     ^categoryArray! !
  20469.  
  20470. !ClassOrganizer methodsFor: 'accessing'!
  20471. categories: anArray 
  20472.     "Reorder my categories to be in order of the argument, anArray. If the 
  20473.     resulting organization does not include all elements, then give an error."
  20474.  
  20475.     | newCategories newStops newElements catName list runningTotal | 
  20476.     newCategories _ Array new: anArray size.
  20477.     newStops _ Array new: anArray size.
  20478.     newElements _ Array new: 0.
  20479.     runningTotal _ 0.
  20480.     1 to: anArray size do:
  20481.         [:i |
  20482.         catName _ (anArray at: i) asSymbol.
  20483.         list _ self listAtCategoryNamed: catName.
  20484.                 newElements _ newElements, list.
  20485.                 newCategories at: i put: catName.
  20486.                 newStops at: i put: (runningTotal _ runningTotal + list size)].
  20487.     elementArray do:
  20488.         [:element | "check to be sure all elements are included"
  20489.         (newElements includes: element)
  20490.             ifFalse: [^self error: 'New categories must match old ones']].
  20491.     "Everything is good, now update my three arrays."
  20492.     categoryArray _ newCategories.
  20493.     categoryStops _ newStops.
  20494.     elementArray _ newElements! !
  20495.  
  20496. !ClassOrganizer methodsFor: 'accessing'!
  20497. categoryOfElement: element 
  20498.     "Answer the category associated with the argument, element."
  20499.  
  20500.     | index |
  20501.     index _ self numberOfCategoryOfElement: element.
  20502.     index = 0
  20503.         ifTrue: [^nil]
  20504.         ifFalse: [^categoryArray at: index]! !
  20505.  
  20506. !ClassOrganizer methodsFor: 'accessing' stamp: 'tk 9/30/97 11:00'!
  20507. changeFromString: aString 
  20508.     "Parse the argument, aString, and make this be the receiver's structure."
  20509.  
  20510.     | scanner oldElements newElements newCategories newStops currentStop anArray temp ii cc |
  20511.     scanner _ Scanner new scanTokens: aString.
  20512.     "If nothing was scanned and I had no elements before, then default me"
  20513.     (scanner size = 0 and: [elementArray size = 0])
  20514.         ifTrue: [^self setDefaultList: Array new].
  20515.  
  20516.     oldElements _ elementArray asSet.
  20517.     newCategories _ Array new: scanner size.
  20518.     newStops _ Array new: scanner size.
  20519.     currentStop _ 0.
  20520.     newElements _ WriteStream on: (Array new: 16).
  20521.     1 to: scanner size do: 
  20522.         [:i | 
  20523.         anArray _ scanner at: i.
  20524.         newCategories at: i put: anArray first asSymbol.
  20525.         anArray allButFirst asSortedCollection do:
  20526.             [:elem |
  20527.             (oldElements remove: elem ifAbsent: [nil]) notNil ifTrue:
  20528.                 [newElements nextPut: elem.
  20529.                 currentStop _ currentStop+1]].
  20530.         newStops at: i put: currentStop].
  20531.  
  20532.     "Ignore extra elements but don't lose any existing elements!!"
  20533.     oldElements _ oldElements collect:
  20534.         [:elem | Array with: (self categoryOfElement: elem) with: elem].
  20535.     newElements _ newElements contents.
  20536.     categoryArray _ newCategories.
  20537.     (cc _ categoryArray asSet) size = categoryArray size ifFalse: ["has duplicate element"
  20538.         temp _ categoryArray asOrderedCollection.
  20539.         temp removeAll: categoryArray asSet asOrderedCollection.
  20540.         temp do: [:dup | 
  20541.             ii _ categoryArray indexOf: dup.
  20542.             [dup _ (dup,' #2') asSymbol.  cc includes: dup] whileTrue.
  20543.             cc add: dup.
  20544.             categoryArray at: ii put: dup]].
  20545.     categoryStops _ newStops.
  20546.     elementArray _ newElements.
  20547.     oldElements do: [:pair | self classify: pair last under: pair first].! !
  20548.  
  20549. !ClassOrganizer methodsFor: 'accessing' stamp: 'tk 12/12/97 13:32'!
  20550. classComment
  20551.     "Answer the comment associated with the object that refers to the 
  20552.     receiver."
  20553.  
  20554.     globalComment == nil ifTrue: [^''].
  20555.     ^globalComment text! !
  20556.  
  20557. !ClassOrganizer methodsFor: 'accessing' stamp: 'tk 12/16/97 07:44'!
  20558. classComment: aString 
  20559.     "Store the comment, aString, associated with the object that refers to the 
  20560.     receiver."
  20561.  
  20562.     (aString isKindOf: RemoteString) 
  20563.         ifTrue: [globalComment _ aString]
  20564.         ifFalse: [aString size = 0
  20565.             ifTrue: [globalComment _ nil]
  20566.             ifFalse: [
  20567.                 self error: 'use aClass classComment:'.
  20568.                 globalComment _ RemoteString newString: aString onFileNumber: 2]]
  20569.                 "Later add priorSource and date and initials?"! !
  20570.  
  20571. !ClassOrganizer methodsFor: 'accessing' stamp: 'tk 12/15/97 14:41'!
  20572. commentRemoteStr
  20573.     ^ globalComment! !
  20574.  
  20575. !ClassOrganizer methodsFor: 'accessing'!
  20576. hasNoComment
  20577.     "Answer whether the class classified by the receiver has a comment."
  20578.  
  20579.     ^globalComment == nil! !
  20580.  
  20581. !ClassOrganizer methodsFor: 'accessing'!
  20582. listAtCategoryNamed: categoryName
  20583.     "Answer the array of elements associated with the name, categoryName."
  20584.  
  20585.     | i |
  20586.     i _ categoryArray indexOf: categoryName ifAbsent: [^Array new].
  20587.     ^self listAtCategoryNumber: i! !
  20588.  
  20589. !ClassOrganizer methodsFor: 'accessing'!
  20590. listAtCategoryNumber: anInteger 
  20591.     "Answer the array of elements stored at the position indexed by 
  20592.     anInteger."
  20593.  
  20594.     | firstIndex lastIndex |
  20595.     firstIndex _ 
  20596.         (anInteger > 1
  20597.             ifTrue: [categoryStops at: anInteger - 1]
  20598.             ifFalse: [0])
  20599.         + 1.
  20600.     lastIndex _ categoryStops at: anInteger.
  20601.     ^elementArray copyFrom: firstIndex to: lastIndex! !
  20602.  
  20603. !ClassOrganizer methodsFor: 'accessing'!
  20604. numberOfCategoryOfElement: element 
  20605.     "Answer the index of the category with which the argument, element, is 
  20606.     associated."
  20607.  
  20608.     | categoryIndex elementIndex |
  20609.     categoryIndex _ 1.
  20610.     elementIndex _ 0.
  20611.     [(elementIndex _ elementIndex + 1) <= elementArray size]
  20612.         whileTrue: 
  20613.             ["point to correct category"
  20614.             [elementIndex > (categoryStops at: categoryIndex)]
  20615.                 whileTrue: [categoryIndex _ categoryIndex + 1].
  20616.             "see if this is element"
  20617.             element = (elementArray at: elementIndex) ifTrue: [^categoryIndex]].
  20618.     ^0! !
  20619.  
  20620. !ClassOrganizer methodsFor: 'accessing'!
  20621. removeElement: element 
  20622.     "Remove the selector, element, from all categories."
  20623.     | categoryIndex elementIndex nextStop newElements |
  20624.     categoryIndex _ 1.
  20625.     elementIndex _ 0.
  20626.     nextStop _ 0.
  20627.     "nextStop keeps track of the stops in the new element array"
  20628.     newElements _ WriteStream on: (Array new: elementArray size).
  20629.     [(elementIndex _ elementIndex + 1) <= elementArray size]
  20630.         whileTrue: 
  20631.             [[elementIndex > (categoryStops at: categoryIndex)]
  20632.                 whileTrue: 
  20633.                     [categoryStops at: categoryIndex put: nextStop.
  20634.                     categoryIndex _ categoryIndex + 1].
  20635.             (elementArray at: elementIndex) = element
  20636.                 ifFalse: 
  20637.                     [nextStop _ nextStop + 1.
  20638.                     newElements nextPut: (elementArray at: elementIndex)]].
  20639.     [categoryIndex <= categoryStops size]
  20640.         whileTrue: 
  20641.             [categoryStops at: categoryIndex put: nextStop.
  20642.             categoryIndex _ categoryIndex + 1].
  20643.     elementArray _ newElements contents! !
  20644.  
  20645. !ClassOrganizer methodsFor: 'accessing'!
  20646. removeEmptyCategories
  20647.     "Remove empty categories."
  20648.  
  20649.     | categoryIndex currentStop keptCategories keptStops |
  20650.     keptCategories _ WriteStream on: (Array new: 16).
  20651.     keptStops _ WriteStream on: (Array new: 16).
  20652.     currentStop _ categoryIndex _ 0.
  20653.     [(categoryIndex _ categoryIndex + 1) <= categoryArray size]
  20654.         whileTrue: 
  20655.             [(categoryStops at: categoryIndex) > currentStop
  20656.                 ifTrue: 
  20657.                     [keptCategories nextPut: (categoryArray at: categoryIndex).
  20658.                     keptStops nextPut: (currentStop _ categoryStops at: categoryIndex)]].
  20659.     categoryArray _ keptCategories contents.
  20660.     categoryStops _ keptStops contents.
  20661.     categoryArray size = 0
  20662.         ifTrue:
  20663.             [categoryArray _ Array with: Default.
  20664.             categoryStops _ Array with: 0]
  20665.  
  20666.     "ClassOrganizer allInstancesDo: [:co | co removeEmptyCategories]."! !
  20667.  
  20668.  
  20669. !ClassOrganizer methodsFor: 'compiler access' stamp: 'tk 5/18/1998 11:32'!
  20670. classify: element under: heading 
  20671.     "Store the argument, element, in the category named heading."
  20672.  
  20673.     | catName catIndex elemIndex realHeading |
  20674.     ((heading = NullCategory) or: [heading == nil])
  20675.         ifTrue: [realHeading _ Default]
  20676.         ifFalse: [realHeading _ heading asSymbol].
  20677.     (catName _ self categoryOfElement: element) = realHeading
  20678.         ifTrue: [^self].  "done if already under that category"
  20679.  
  20680.     catName ~~ nil ifTrue: 
  20681.         [realHeading = Default
  20682.             ifTrue: [^self].    "return if exists and realHeading is default"
  20683.         self removeElement: element].    "remove if in another category"
  20684.  
  20685.     (categoryArray indexOf: realHeading) = 0 ifTrue: [self addCategory: realHeading].
  20686.     "add realHeading if not there already"
  20687.  
  20688.     catIndex _ categoryArray indexOf: realHeading.
  20689.     elemIndex _ 
  20690.         catIndex > 1
  20691.             ifTrue: [categoryStops at: catIndex - 1]
  20692.             ifFalse: [0].
  20693.     [(elemIndex _ elemIndex + 1) <= (categoryStops at: catIndex) 
  20694.         and: [element >= (elementArray at: elemIndex)]] whileTrue.
  20695.  
  20696.     "elemIndex is now the index for inserting the element. Do the insertion before it."
  20697.     elementArray _ elementArray copyReplaceFrom: elemIndex to: elemIndex-1
  20698.                         with: (Array with: element).
  20699.  
  20700.     "add one to stops for this and later categories"
  20701.     catIndex to: categoryArray size do: 
  20702.         [:i | categoryStops at: i put: (categoryStops at: i) + 1].
  20703.     (self listAtCategoryNamed: Default) size = 0 ifTrue: [self removeCategory: Default]! !
  20704.  
  20705. !ClassOrganizer methodsFor: 'compiler access'!
  20706. classifyAll: aCollection under: heading
  20707.  
  20708.     aCollection do:
  20709.         [:element | self classify: element under: heading]! !
  20710.  
  20711.  
  20712. !ClassOrganizer methodsFor: 'method dictionary'!
  20713. addCategory: newCategory
  20714.     ^ self addCategory: newCategory before: nil ! !
  20715.  
  20716. !ClassOrganizer methodsFor: 'method dictionary'!
  20717. addCategory: catString before: nextCategory
  20718.     "Add a new category named heading.
  20719.     If default category exists and is empty, remove it.
  20720.     If nextCategory is nil, then add the new one at the end,
  20721.     otherwise, insert it before nextCategory."
  20722.     | index newCategory |
  20723.     newCategory _ catString asSymbol.
  20724.     (categoryArray indexOf: newCategory) > 0
  20725.         ifTrue: [^self].    "heading already exists, so done"
  20726.     index _ categoryArray indexOf: nextCategory
  20727.         ifAbsent: [categoryArray size + 1].
  20728.     categoryArray _ categoryArray
  20729.         copyReplaceFrom: index
  20730.         to: index-1
  20731.         with: (Array with: newCategory).
  20732.     categoryStops _ categoryStops
  20733.         copyReplaceFrom: index
  20734.         to: index-1
  20735.         with: (Array with: (index = 1
  20736.                 ifTrue: [0]
  20737.                 ifFalse: [categoryStops at: index-1])).
  20738.     "remove empty default category"
  20739.     (newCategory ~= Default
  20740.             and: [(self listAtCategoryNamed: Default) isEmpty])
  20741.         ifTrue: [self removeCategory: Default]! !
  20742.  
  20743. !ClassOrganizer methodsFor: 'method dictionary'!
  20744. removeCategory: cat 
  20745.     "Remove the category named, cat. Create an error notificiation if the 
  20746.     category has any elements in it."
  20747.  
  20748.     | index lastStop |
  20749.     index _ categoryArray indexOf: cat ifAbsent: [^self].
  20750.     lastStop _ 
  20751.         index = 1
  20752.             ifTrue: [0]
  20753.             ifFalse: [categoryStops at: index - 1].
  20754.     (categoryStops at: index) - lastStop > 0 
  20755.         ifTrue: [^self error: 'cannot remove non-empty category'].
  20756.     categoryArray _ categoryArray copyReplaceFrom: index to: index with: Array new.
  20757.     categoryStops _ categoryStops copyReplaceFrom: index to: index with: Array new.
  20758.     categoryArray size = 0
  20759.         ifTrue:
  20760.             [categoryArray _ Array with: Default.
  20761.             categoryStops _ Array with: 0]
  20762. ! !
  20763.  
  20764. !ClassOrganizer methodsFor: 'method dictionary'!
  20765. renameCategory: oldCatString toBe: newCatString
  20766.     "Rename a category. No action if new name already exists,
  20767.     or if old name does not exist."
  20768.     | index oldCategory newCategory |
  20769.     oldCategory _ oldCatString asSymbol.
  20770.     newCategory _ newCatString asSymbol.
  20771.     (categoryArray indexOf: newCategory) > 0
  20772.         ifTrue: [^self].    "new name exists, so no action"
  20773.     (index _ categoryArray indexOf: oldCategory) = 0
  20774.         ifTrue: [^self].    "old name not found, so no action"
  20775.     categoryArray at: index put: newCategory! !
  20776.  
  20777.  
  20778. !ClassOrganizer methodsFor: 'printing'!
  20779. printOn: aStream 
  20780.     "Refer to the comment in Object|printOn:."
  20781.  
  20782.     | elementIndex lastStop |
  20783.     elementIndex _ 1.
  20784.     lastStop _ 1.
  20785.     1 to: categoryArray size do: 
  20786.         [:i | 
  20787.         aStream nextPut: $(.
  20788.         (categoryArray at: i) asString printOn: aStream.
  20789.         [elementIndex <= (categoryStops at: i)]
  20790.             whileTrue: 
  20791.                 [aStream space.
  20792.                 (elementArray at: elementIndex) printOn: aStream.
  20793.                 elementIndex _ elementIndex + 1].
  20794.         aStream nextPut: $).
  20795.         aStream cr]! !
  20796.  
  20797.  
  20798. !ClassOrganizer methodsFor: 'fileIn/Out'!
  20799. fileOutCommentOn: aFileStream moveSource: moveSource toFile: fileIndex
  20800.     "Copy the class comment to aFileStream.  If moveSource is true (as in compressChanges or compressSources, then update globalComment to point to the new file."
  20801.     | fileComment |
  20802.     globalComment ifNotNil: 
  20803.             [aFileStream cr.
  20804.             fileComment _ RemoteString newString: globalComment text
  20805.                             onFileNumber: fileIndex toFile: aFileStream.
  20806.             moveSource ifTrue: [globalComment _ fileComment]]! !
  20807.  
  20808. !ClassOrganizer methodsFor: 'fileIn/Out'!
  20809. moveChangedCommentToFile: aFileStream numbered: fileIndex 
  20810.     "If the comment is in the changes file, then move it to a new file."
  20811.  
  20812.     (globalComment ~~ nil and: [globalComment sourceFileNumber > 1]) ifTrue: 
  20813.         [self fileOutCommentOn: aFileStream moveSource: true toFile: fileIndex]! !
  20814.  
  20815. !ClassOrganizer methodsFor: 'fileIn/Out'!
  20816. putCommentOnFile: aFileStream numbered: sourceIndex moveSource: moveSource forClass: aClass
  20817.     "Store the comment about the class onto file, aFileStream."
  20818.     | header |
  20819.     globalComment ifNotNil:
  20820.         [aFileStream cr; nextPut: $!!.
  20821.         header _ String streamContents: [:strm | 
  20822.                 strm nextPutAll: aClass name;
  20823.                 nextPutAll: ' commentStamp: '.
  20824.                 Utilities changeStamp storeOn: strm.
  20825.                 strm nextPutAll: ' prior: '; nextPutAll: '0'].
  20826.         aFileStream nextChunkPut: header.
  20827.         aClass organization fileOutCommentOn: aFileStream
  20828.                 moveSource: moveSource toFile: sourceIndex.
  20829.         aFileStream cr]! !
  20830.  
  20831. !ClassOrganizer methodsFor: 'fileIn/Out' stamp: 'di 1/13/98 16:57'!
  20832. scanFrom: aStream
  20833.     "Reads in the organization from the next chunk on aStream.
  20834.     Categories or elements not found in the definition are not affected.
  20835.     New elements are ignored."
  20836.  
  20837.     self changeFromString: aStream nextChunk.
  20838.     aStream skipStyleChunk.! !
  20839.  
  20840.  
  20841. !ClassOrganizer methodsFor: 'private' stamp: 'tk 12/16/97 07:35'!
  20842. setDefaultList: aSortedCollection
  20843.  
  20844.     self classComment: ''.
  20845.     categoryArray _ Array with: Default.
  20846.     categoryStops _ Array with: aSortedCollection size.
  20847.     elementArray _ aSortedCollection asArray! !
  20848.  
  20849. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  20850.  
  20851. ClassOrganizer class
  20852.     instanceVariableNames: ''!
  20853.  
  20854. !ClassOrganizer class methodsFor: 'class initialization'!
  20855. default 
  20856.     ^ Default! !
  20857.  
  20858. !ClassOrganizer class methodsFor: 'class initialization'!
  20859. initialize
  20860.     Default _ 'as yet unclassified' asSymbol.
  20861.     NullCategory _ 'no messages' asSymbol.
  20862.     "ClassOrganizer initialize"! !
  20863.  
  20864. !ClassOrganizer class methodsFor: 'class initialization'!
  20865. nullCategory
  20866.     ^ NullCategory! !
  20867.  
  20868.  
  20869. !ClassOrganizer class methodsFor: 'instance creation'!
  20870. defaultList: aSortedCollection 
  20871.     "Answer an instance of me with initial elements from the argument, 
  20872.     aSortedCollection."
  20873.  
  20874.     ^self new setDefaultList: aSortedCollection! !
  20875.  
  20876.  
  20877. !ClassOrganizer class methodsFor: 'documentation'!
  20878. documentation
  20879.     "Instances consist of an Array of category names (categoryArray), each of 
  20880.     which refers to an Array of elements (elementArray). This association is 
  20881.     made through an Array of stop indices (categoryStops), each of which is 
  20882.     the index in elementArray of the last element (if any) of the 
  20883.     corresponding category. For example: categories _ Array with: 'firstCat' 
  20884.     with: 'secondCat' with: 'thirdCat'. stops _ Array with: 1 with: 4 with: 4. 
  20885.     elements _ Array with: #a with: #b with: #c with: #d. This means that 
  20886.     category firstCat has only #a, secondCat has #b, #c, and #d, and 
  20887.     thirdCat has no elements. This means that stops at: stops size must be the 
  20888.     same as elements size." ! !
  20889. StringMorph subclass: #ClockMorph
  20890.     instanceVariableNames: ''
  20891.     classVariableNames: ''
  20892.     poolDictionaries: ''
  20893.     category: 'Morphic-Demo'!
  20894.  
  20895. !ClockMorph methodsFor: 'all' stamp: 'sw 2/9/98 01:23'!
  20896. step
  20897.     super step.
  20898.     self contents: Time now printString.! !
  20899.  
  20900. !ClockMorph methodsFor: 'all'!
  20901. stepTime
  20902.     "Answer the desired time between steps in milliseconds."
  20903.  
  20904.     ^ 1000! !
  20905. ServerAction subclass: #CodeServer
  20906.     instanceVariableNames: ''
  20907.     classVariableNames: ''
  20908.     poolDictionaries: ''
  20909.     category: 'PluggableWebServer'!
  20910. !CodeServer commentStamp: 'di 5/22/1998 16:32' prior: 0!
  20911. Return the source code from Smalltalk, as web page text, or as a raw Squeak file chunk.
  20912. URLs are of the form:    
  20913.     machine:80/smtlk.Point|min;            <-- NOTE: use ; instead of :
  20914.     machine:80/smtlk.{Class}|{selector}
  20915.     machine:80/chunk.{Class}|{selector}
  20916.  
  20917.     machine:80/smtlk.{Class}|class|{selector}
  20918.     machine:80/chunk.{Class}|class|{selector}
  20919.  
  20920.     machine:80/smtlk.{Class}|Definition
  20921.     machine:80/chunk.{Class}|Definition
  20922.  
  20923.     machine:80/smtlk.{Class}|Hierarchy
  20924.     machine:80/chunk.{Class}|Hierarchy
  20925.  
  20926.     machine:80/smtlk.{Class}|Comment
  20927.     machine:80/chunk.{Class}|Comment
  20928. NOTE: use ; semicolon instead of : colon in selector names
  20929. !
  20930.  
  20931.  
  20932. !CodeServer methodsFor: 'as yet unclassified' stamp: 'tk 5/7/1998 15:36'!
  20933. chunk: request
  20934.     "Return Smalltalk source code as a chunk from the changes file.  
  20935. URL = machine:80/chunk.Point|min;  included are:  Point|at;   Point|Comment   Point|Hierarchy  Point|Definition   Point|class|x;y;
  20936.     Meant to be received by a Squeak client, not a browser.  Reply not in HTML"
  20937.  
  20938.     | classAndMethod set strm chunk |
  20939.     classAndMethod _ request message atPin: 2.
  20940.     classAndMethod _ classAndMethod copyReplaceAll: '|' with: ' '.
  20941.     classAndMethod _ classAndMethod copyReplaceAll: ';' with: ':'.
  20942.     set _ LinkedMessageSet messageList: (Array with: classAndMethod).
  20943.     strm _ WriteStream on: (String new: 300).
  20944.     strm nextChunkPutWithStyle: (set selectedMessage). "String or text"
  20945.     chunk _ strm contents.
  20946.  
  20947.     request reply: 'content-length: ', chunk size printString, PWS crlfcrlf.
  20948.     request reply: chunk.
  20949. ! !
  20950.  
  20951. !CodeServer methodsFor: 'as yet unclassified' stamp: 'tk 5/7/1998 15:35'!
  20952. process: request
  20953.     "Return the source code from Smalltalk, as text or as a chunk.
  20954. URLs are of this form.  Each may have 'chunk' or 'smtlk' as the thing after the slash
  20955.     machine:80/smtlk.Point|min;
  20956.     machine:80/chunk.{Class}|{selector}        
  20957.     machine:80/smtlk.{Class}|{selector}
  20958.     machine:80/smtlk.{Class}|class|{selector}
  20959.     machine:80/smtlk.{Class}|Definition
  20960.     machine:80/smtlk.{Class}|Hierarchy
  20961.     machine:80/smtlk.{Class}|Comment
  20962. NOTE: use ; semicolon instead of : colon in selector names!!!!!!"
  20963.  
  20964.     | coreRef |
  20965.     coreRef _ (request message at: 1) asLowercase.
  20966.     request reply: PWS success; reply: PWS contentHTML.
  20967.     Transcript show: 'In process: ', request message printString; cr.
  20968.     coreRef = 'smtlk' ifTrue: [^ self smtlk: request].
  20969.     coreRef = 'chunk' ifTrue: [^ self chunk: request].
  20970.     request reply: ( 'HTTP/1.0 400 Bad Request', PWS crlfcrlf, 
  20971.         'expected smtlk.{Class}|{selector} or chunk.{Class}|{selector}').    "failure"! !
  20972.  
  20973. !CodeServer methodsFor: 'as yet unclassified' stamp: 'tk 5/7/1998 15:36'!
  20974. smtlk: request
  20975.     "Return Smalltalk sourcecode in HTML.  URL = machine:80/myswiki.smtlk.Point|min;  included are:  Point|min;   Point|Comment   Point|Hierarchy  Point|Definition   Point|class|x;y;  
  20976. NOTE: use ; instead of : in selector names!!!!!!"
  20977.  
  20978.     | classAndMethod set |
  20979.     classAndMethod _ request message atPin: 2.
  20980.     classAndMethod _ classAndMethod copyReplaceAll: '|' with: ' '.
  20981.     classAndMethod _ classAndMethod copyReplaceAll: ';' with: ':'.
  20982.     set _ LinkedMessageSet messageList: (Array with: classAndMethod).
  20983.  
  20984.     request reply: PWS crlf, (HTMLformatter 
  20985.                 evalEmbedded: (self fileContents: 'swiki',(ServerAction pathSeparator),'smtlk.html')
  20986.                 with: set).! !
  20987. Object subclass: #Collection
  20988.     instanceVariableNames: ''
  20989.     classVariableNames: 'RandomForPicking '
  20990.     poolDictionaries: ''
  20991.     category: 'Collections-Abstract'!
  20992. !Collection commentStamp: 'di 5/22/1998 16:32' prior: 0!
  20993. Collection comment:
  20994. 'I am the abstract superclass of all classes that represent a group of elements.'!
  20995.  
  20996.  
  20997. !Collection methodsFor: 'accessing'!
  20998. size
  20999.     "Answer how many elements the receiver contains."
  21000.  
  21001.     | tally |
  21002.     tally _ 0.
  21003.     self do: [:each | tally _ tally + 1].
  21004.     ^tally! !
  21005.  
  21006.  
  21007. !Collection methodsFor: 'testing'!
  21008. includes: anObject 
  21009.     "Answer whether anObject is one of the receiver's elements."
  21010.  
  21011.     self do: [:each | anObject = each ifTrue: [^true]].
  21012.     ^false! !
  21013.  
  21014. !Collection methodsFor: 'testing'!
  21015. includesAllOf: aCollection 
  21016.     "Answer whether all the elements of aCollection are in the receiver."
  21017.     aCollection do: [:elem | (self includes: elem) ifFalse: [^ false]].
  21018.     ^ true! !
  21019.  
  21020. !Collection methodsFor: 'testing'!
  21021. includesAnyOf: aCollection 
  21022.     "Answer whether any element of aCollection is one of the receiver's elements."
  21023.     aCollection do: [:elem | (self includes: elem) ifTrue: [^ true]].
  21024.     ^ false! !
  21025.  
  21026. !Collection methodsFor: 'testing' stamp: 'sw 8/12/97 20:59'!
  21027. includesSubstringAnywhere: testString
  21028.     "Answer whether the receiver includes, anywhere in its nested structure, a string that has testString as a substring"
  21029.     self do:
  21030.         [:element |
  21031.             (element isKindOf: String)
  21032.                 ifTrue:
  21033.                     [(element includesSubString: testString) ifTrue: [^ true]].
  21034.             (element isKindOf: Collection)
  21035.                 ifTrue:
  21036.                     [(element includesSubstringAnywhere: testString) ifTrue: [^ true]]].
  21037.     ^ false
  21038.  
  21039. "#(first (second third) ((allSentMessages ('Elvis' includes:)))) includesSubstringAnywhere:  'lvi'"! !
  21040.  
  21041. !Collection methodsFor: 'testing'!
  21042. isEmpty
  21043.     "Answer whether the receiver contains any elements."
  21044.  
  21045.     ^self size = 0! !
  21046.  
  21047. !Collection methodsFor: 'testing'!
  21048. occurrencesOf: anObject 
  21049.     "Answer how many of the receiver's elements are equal to anObject."
  21050.  
  21051.     | tally |
  21052.     tally _ 0.
  21053.     self do: [:each | anObject = each ifTrue: [tally _ tally + 1]].
  21054.     ^tally! !
  21055.  
  21056.  
  21057. !Collection methodsFor: 'adding'!
  21058. add: newObject 
  21059.     "Include newObject as one of the receiver's elements. Answer newObject. 
  21060.     ArrayedCollections cannot respond to this message."
  21061.  
  21062.     self subclassResponsibility! !
  21063.  
  21064. !Collection methodsFor: 'adding'!
  21065. addAll: aCollection 
  21066.     "Include all the elements of aCollection as the receiver's elements. Answer 
  21067.     aCollection."
  21068.  
  21069.     aCollection do: [:each | self add: each].
  21070.     ^aCollection! !
  21071.  
  21072. !Collection methodsFor: 'adding' stamp: 'tk 5/7/1998 13:00'!
  21073. addIfNotPresent: anObject
  21074.  
  21075.     (self includes: anObject) ifFalse: [^ self add: anObject]! !
  21076.  
  21077.  
  21078. !Collection methodsFor: 'removing'!
  21079. remove: oldObject 
  21080.     "Remove oldObject as one of the receiver's elements. Answer oldObject 
  21081.     unless no element is equal to oldObject, in which case, create an error 
  21082.     notification."
  21083.  
  21084.     ^self remove: oldObject ifAbsent: [self errorNotFound]! !
  21085.  
  21086. !Collection methodsFor: 'removing'!
  21087. remove: oldObject ifAbsent: anExceptionBlock 
  21088.     "Remove oldObject as one of the receiver's elements. If several of the 
  21089.     elements are equal to oldObject, only one is removed. If no element is 
  21090.     equal to oldObject, answer the result of evaluating anExceptionBlock. 
  21091.     Otherwise, answer the argument, oldObject. SequenceableCollections 
  21092.     cannot respond to this message."
  21093.  
  21094.     self subclassResponsibility! !
  21095.  
  21096. !Collection methodsFor: 'removing'!
  21097. removeAll: aCollection 
  21098.     "Remove each element of aCollection from the receiver. If successful for 
  21099.     each, answer aCollection. Otherwise create an error notification."
  21100.  
  21101.     aCollection do: [:each | self remove: each].
  21102.     ^aCollection! !
  21103.  
  21104. !Collection methodsFor: 'removing'!
  21105. removeAllFoundIn: aCollection 
  21106.     "Remove each element of aCollection which is present in the receiver from the receiver"
  21107.  
  21108.     aCollection do: [:each | self remove: each ifAbsent: []].
  21109.     ^aCollection! !
  21110.  
  21111. !Collection methodsFor: 'removing'!
  21112. removeAllSuchThat: aBlock
  21113.     "Apply the condition to each element and remove it if the condition is true.  Use a copy to enumerate collections whose order changes when an element is removed (Set)."
  21114.     | copy newCollection |
  21115.     newCollection _ self species new.
  21116.     copy _ self copy.
  21117.     copy do: [:element |
  21118.         (aBlock value: element) ifTrue: [
  21119.             self remove: element.
  21120.             newCollection add: element]].
  21121.     ^ newCollection! !
  21122.  
  21123.  
  21124. !Collection methodsFor: 'enumerating'!
  21125. associationsDo: aBlock
  21126.     "Evaluate aBlock for each of the receiver's elements (key/value 
  21127.     associations).  If any non-association is within, the error is not caught now,
  21128.     but later, when a key or value message is sent to it."
  21129.  
  21130.     self do: aBlock! !
  21131.  
  21132. !Collection methodsFor: 'enumerating' stamp: 'jm 10/16/97 21:25'!
  21133. average
  21134.     "Return the average of all my elements."
  21135.  
  21136.     ^ self sum asFloat / self size
  21137. ! !
  21138.  
  21139. !Collection methodsFor: 'enumerating'!
  21140. collect: aBlock 
  21141.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21142.     Collect the resulting values into a collection like the receiver. Answer 
  21143.     the new collection."
  21144.  
  21145.     | newCollection |
  21146.     newCollection _ self species new.
  21147.     self do: [:each | newCollection add: (aBlock value: each)].
  21148.     ^newCollection! !
  21149.  
  21150. !Collection methodsFor: 'enumerating'!
  21151. collect: collectBlock thenSelect: selectBlock
  21152.     ^ (self collect: collectBlock) select: selectBlock! !
  21153.  
  21154. !Collection methodsFor: 'enumerating'!
  21155. count: aBlock
  21156.     "Evaluate aBlock with each of the receiver's elements as the argument.  Return the number that answered true."
  21157.  
  21158.     | sum |
  21159.     sum _ 0.
  21160.     self do: [:each | 
  21161.         (aBlock value: each) ifTrue: [sum _ sum + 1]].
  21162.     ^ sum! !
  21163.  
  21164. !Collection methodsFor: 'enumerating'!
  21165. detect: aBlock 
  21166.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21167.     Answer the first element for which aBlock evaluates to true."
  21168.  
  21169.     ^self detect: aBlock ifNone: [self errorNotFound]! !
  21170.  
  21171. !Collection methodsFor: 'enumerating'!
  21172. detect: aBlock ifNone: exceptionBlock 
  21173.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21174.     Answer the first element for which aBlock evaluates to true. If none 
  21175.     evaluate to true, then evaluate the argument, exceptionBlock."
  21176.  
  21177.     self do: [:each | (aBlock value: each) ifTrue: [^each]].
  21178.     ^exceptionBlock value! !
  21179.  
  21180. !Collection methodsFor: 'enumerating'!
  21181. detectMax: aBlock
  21182.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21183.     Answer the element for which aBlock evaluates to the highest magnitude.
  21184.     If collection empty, return nil.  This method might also be called elect:."
  21185.  
  21186.     | maxElement maxValue val |
  21187.     self do: [:each | 
  21188.         maxValue == nil
  21189.             ifFalse: [
  21190.                 (val _ aBlock value: each) > maxValue ifTrue: [
  21191.                     maxElement _ each.
  21192.                     maxValue _ val]]
  21193.             ifTrue: ["first element"
  21194.                 maxElement _ each.
  21195.                 maxValue _ aBlock value: each].
  21196.                 "Note that there is no way to get the first element that works 
  21197.                 for all kinds of Collections.  Must test every one."].
  21198.     ^ maxElement! !
  21199.  
  21200. !Collection methodsFor: 'enumerating'!
  21201. detectMin: aBlock
  21202.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21203.     Answer the element for which aBlock evaluates to the lowest number.
  21204.     If collection empty, return nil."
  21205.  
  21206.     | minElement minValue val |
  21207.     self do: [:each | 
  21208.         minValue == nil
  21209.             ifFalse: [
  21210.                 (val _ aBlock value: each) < minValue ifTrue: [
  21211.                     minElement _ each.
  21212.                     minValue _ val]]
  21213.             ifTrue: ["first element"
  21214.                 minElement _ each.
  21215.                 minValue _ aBlock value: each].
  21216.                 "Note that there is no way to get the first element that works 
  21217.                 for all kinds of Collections.  Must test every one."].
  21218.     ^ minElement! !
  21219.  
  21220. !Collection methodsFor: 'enumerating'!
  21221. detectSum: aBlock
  21222.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21223.     Return the sum of the answers."
  21224.     | sum |
  21225.     sum _ 0.
  21226.     self do: [:each | 
  21227.         sum _ (aBlock value: each) + sum].  
  21228.     ^ sum! !
  21229.  
  21230. !Collection methodsFor: 'enumerating'!
  21231. do: aBlock 
  21232.     "Evaluate aBlock with each of the receiver's elements as the argument."
  21233.  
  21234.     self subclassResponsibility! !
  21235.  
  21236. !Collection methodsFor: 'enumerating'!
  21237. inject: thisValue into: binaryBlock 
  21238.     "Accumulate a running value associated with evaluating the argument, 
  21239.     binaryBlock, with the current value of the argument, thisValue, and the 
  21240.     receiver as block arguments. For instance, to sum the numeric elements 
  21241.     of a collection, aCollection inject: 0 into: [:subTotal :next | subTotal + 
  21242.     next]."
  21243.  
  21244.     | nextValue |
  21245.     nextValue _ thisValue.
  21246.     self do: [:each | nextValue _ binaryBlock value: nextValue value: each].
  21247.     ^nextValue! !
  21248.  
  21249. !Collection methodsFor: 'enumerating' stamp: 'jm 11/14/97 11:08'!
  21250. max
  21251.     "Return the max of all my elements."
  21252.     | max | max _ nil.
  21253.     self do: [:each | (max == nil or: [each > max])
  21254.                     ifTrue: [max _ each]].  
  21255.     ^ max! !
  21256.  
  21257. !Collection methodsFor: 'enumerating'!
  21258. reject: aBlock 
  21259.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21260.     Collect into a new collection like the receiver only those elements for 
  21261.     which aBlock evaluates to false. Answer the new collection."
  21262.  
  21263.     ^self select: [:element | (aBlock value: element) == false]! !
  21264.  
  21265. !Collection methodsFor: 'enumerating'!
  21266. select: aBlock 
  21267.     "Evaluate aBlock with each of the receiver's elements as the argument. 
  21268.     Collect into a new collection like the receiver, only those elements for 
  21269.     which aBlock evaluates to true. Answer the new collection."
  21270.  
  21271.     | newCollection |
  21272.     newCollection _ self species new.
  21273.     self do: [:each | (aBlock value: each) ifTrue: [newCollection add: each]].
  21274.     ^newCollection! !
  21275.  
  21276. !Collection methodsFor: 'enumerating'!
  21277. select: selectBlock thenCollect: collectBlock
  21278.     ^ (self select: selectBlock) collect: collectBlock! !
  21279.  
  21280. !Collection methodsFor: 'enumerating' stamp: 'di 7/5/97 14:56'!
  21281. sum
  21282.     "Return the sum of all my elements."
  21283.     | sum |  sum _ 0.
  21284.     self do: [:each | sum _ sum + each].  
  21285.     ^ sum! !
  21286.  
  21287.  
  21288. !Collection methodsFor: 'converting'!
  21289. asBag
  21290.     "Answer a Bag whose elements are the elements of the receiver."
  21291.  
  21292.     | aBag |
  21293.     aBag _ Bag new.
  21294.     self do: [:each | aBag add: each].
  21295.     ^aBag! !
  21296.  
  21297. !Collection methodsFor: 'converting'!
  21298. asOrderedCollection
  21299.     "Answer an OrderedCollection whose elements are the elements of the 
  21300.     receiver. The order in which elements are added depends on the order in 
  21301.     which the receiver enumerates its elements. In the case of unordered 
  21302.     collections, the ordering is not necessarily the same for multiple requests 
  21303.     for the conversion."
  21304.  
  21305.     | anOrderedCollection |
  21306.     anOrderedCollection _ OrderedCollection new: self size.
  21307.     self do: [:each | anOrderedCollection addLast: each].
  21308.     ^anOrderedCollection! !
  21309.  
  21310. !Collection methodsFor: 'converting'!
  21311. asSet
  21312.     "Answer a Set whose elements are the unique elements of the receiver."
  21313.  
  21314.     | aSet |
  21315.     aSet _ Set new: self size.
  21316.     self do: [:each | aSet add: each].
  21317.     ^aSet! !
  21318.  
  21319. !Collection methodsFor: 'converting'!
  21320. asSortedArray
  21321.     "Return a copy of the receiver in sorted order, as an Array.  6/10/96 sw"
  21322.  
  21323.     ^ self asSortedCollection asArray! !
  21324.  
  21325. !Collection methodsFor: 'converting'!
  21326. asSortedCollection
  21327.     "Answer a SortedCollection whose elements are the elements of the 
  21328.     receiver. The sort order is the default less than or equal."
  21329.  
  21330.     | aSortedCollection |
  21331.     aSortedCollection _ SortedCollection new: self size.
  21332.     aSortedCollection addAll: self.
  21333.     ^aSortedCollection! !
  21334.  
  21335. !Collection methodsFor: 'converting'!
  21336. asSortedCollection: aBlock 
  21337.     "Answer a SortedCollection whose elements are the elements of the 
  21338.     receiver. The sort order is defined by the argument, aBlock."
  21339.  
  21340.     | aSortedCollection |
  21341.     aSortedCollection _ SortedCollection new: self size.
  21342.     aSortedCollection sortBlock: aBlock.
  21343.     aSortedCollection addAll: self.
  21344.     ^aSortedCollection! !
  21345.  
  21346.  
  21347. !Collection methodsFor: 'printing' stamp: 'di 6/20/97 09:09'!
  21348. printOn: aStream 
  21349.     "Refer to the comment in Object|printOn:."
  21350.     aStream nextPutAll: self class name, ' ('.
  21351.     self do: [:element | element printOn: aStream. aStream space].
  21352.     aStream nextPut: $)! !
  21353.  
  21354. !Collection methodsFor: 'printing'!
  21355. storeOn: aStream 
  21356.     "Refer to the comment in Object|storeOn:."
  21357.  
  21358.     | noneYet |
  21359.     aStream nextPutAll: '(('.
  21360.     aStream nextPutAll: self class name.
  21361.     aStream nextPutAll: ' new)'.
  21362.     noneYet _ true.
  21363.     self do: 
  21364.         [:each | 
  21365.         noneYet
  21366.             ifTrue: [noneYet _ false]
  21367.             ifFalse: [aStream nextPut: $;].
  21368.         aStream nextPutAll: ' add: '.
  21369.         aStream store: each].
  21370.     noneYet ifFalse: [aStream nextPutAll: '; yourself'].
  21371.     aStream nextPut: $)! !
  21372.  
  21373.  
  21374. !Collection methodsFor: 'private'!
  21375. emptyCheck
  21376.  
  21377.     self isEmpty ifTrue: [self errorEmptyCollection]! !
  21378.  
  21379. !Collection methodsFor: 'private'!
  21380. errorEmptyCollection
  21381.  
  21382.     self error: 'this collection is empty'! !
  21383.  
  21384. !Collection methodsFor: 'private'!
  21385. errorNoMatch
  21386.  
  21387.     self error: 'collection sizes do not match'! !
  21388.  
  21389. !Collection methodsFor: 'private'!
  21390. errorNotFound
  21391.  
  21392.     self error: 'Object is not in the collection.'! !
  21393.  
  21394. !Collection methodsFor: 'private'!
  21395. errorNotKeyed
  21396.  
  21397.     self error: self class name, 's do not respond to keyed accessing messages.'! !
  21398.  
  21399. !Collection methodsFor: 'private'!
  21400. fill: numElements fromStack: aContext 
  21401.     "Fill me with numElements elements, popped in reverse order from
  21402.      the stack of aContext.  Do not call directly: this is called indirectly by {1. 2. 3}
  21403.      constructs.  Subclasses that support at:put: instead of add: should override
  21404.      this and call Context<pop:toIndexable:"
  21405.  
  21406.     aContext pop: numElements toAddable: self! !
  21407.  
  21408. !Collection methodsFor: 'private'!
  21409. maxSize
  21410.     "Answer the largest basicSize which is valid for the receiver's class."
  21411.  
  21412.     ^65486 "for VM3 interpreter DoradoST80Aug19"! !
  21413.  
  21414. !Collection methodsFor: 'private'!
  21415. toBraceStack: itsSize 
  21416.     "Push receiver's elements onto the stack of thisContext sender.  Error if receiver does
  21417.      not have itsSize elements or if receiver is unordered.
  21418.      Do not call directly: this is called by {a. b} _ ... constructs."
  21419.  
  21420.     self size ~= itsSize ifTrue:
  21421.         [self error: 'Trying to store ', self size printString,
  21422.                     ' values into ', itsSize printString, ' variables.'].
  21423.     thisContext sender push: itsSize fromIndexable: self! !
  21424.  
  21425. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  21426.  
  21427. Collection class
  21428.     instanceVariableNames: ''!
  21429.  
  21430. !Collection class methodsFor: 'instance creation'!
  21431. fromBraceStack: itsSize 
  21432.     "Answer an instance of me with itsSize elements, popped in reverse order from
  21433.      the stack of thisContext sender.  Do not call directly: this is called by {1. 2. 3}
  21434.      constructs."
  21435.  
  21436.     ^ self newFrom: ((Array new: itsSize) fill: itsSize fromStack: thisContext sender)! !
  21437.  
  21438. !Collection class methodsFor: 'instance creation'!
  21439. with: anObject 
  21440.     "Answer an instance of me containing anObject."
  21441.  
  21442.     | newCollection |
  21443.     newCollection _ self new.
  21444.     newCollection add: anObject.
  21445.     ^newCollection! !
  21446.  
  21447. !Collection class methodsFor: 'instance creation'!
  21448. with: firstObject with: secondObject 
  21449.     "Answer an instance of me containing the two arguments as elements."
  21450.  
  21451.     | newCollection |
  21452.     newCollection _ self new.
  21453.     newCollection add: firstObject.
  21454.     newCollection add: secondObject.
  21455.     ^newCollection! !
  21456.  
  21457. !Collection class methodsFor: 'instance creation'!
  21458. with: firstObject with: secondObject with: thirdObject 
  21459.     "Answer an instance of me containing the three arguments as elements."
  21460.  
  21461.     | newCollection |
  21462.     newCollection _ self new.
  21463.     newCollection add: firstObject.
  21464.     newCollection add: secondObject.
  21465.     newCollection add: thirdObject.
  21466.     ^newCollection! !
  21467.  
  21468. !Collection class methodsFor: 'instance creation'!
  21469. with: firstObject with: secondObject with: thirdObject with: fourthObject 
  21470.     "Answer an instance of me, containing the four arguments as the 
  21471.     elements."
  21472.  
  21473.     | newCollection |
  21474.     newCollection _ self new.
  21475.     newCollection add: firstObject.
  21476.     newCollection add: secondObject.
  21477.     newCollection add: thirdObject.
  21478.     newCollection add: fourthObject.
  21479.     ^newCollection! !
  21480.  
  21481.  
  21482. !Collection class methodsFor: 'private'!
  21483. initialize
  21484.     "Set up a Random number generator to be used by pickOne when the user does not feel like creating his own Random generator."
  21485.     RandomForPicking _ Random new.
  21486.     ! !
  21487. Object subclass: #Color
  21488.     instanceVariableNames: 'rgb cachedDepth cachedBitPattern '
  21489.     classVariableNames: 'Black Blue BlueShift Brown CachedColormaps ColorChart ColorNames ComponentMask ComponentMax Cyan DarkGray Gray GrayToIndexMap Green GreenShift HalfComponentMask HighLightBitmaps IndexedColors LightBlue LightBrown LightCyan LightGray LightGreen LightMagenta LightOrange LightRed LightYellow Magenta MaskingMap OpaqueMask Orange PureBlue PureCyan PureGreen PureMagenta PureRed PureYellow RandomStream Red RedShift Transparent VeryDarkGray VeryLightGray VeryVeryDarkGray VeryVeryLightGray White Yellow '
  21490.     poolDictionaries: ''
  21491.     category: 'Graphics-Display Objects'!
  21492. !Color commentStamp: 'di 5/22/1998 16:32' prior: 0!
  21493. Color comment:
  21494. 'This class represents abstract color, regardless of the depth of bitmap it will be shown in.  At the very last moment a Color is converted to a pixelValue that depends on the depth of the actual Bitmap inside the Form it will be used with.  The supported depths (in bits) are 1, 2, 4, 8, 16, and 32.  The number of actual colors at these depths are: 2, 4, 16, 256, 32768, and 16 million.  (See comment in BitBlt.)  To change the depth of the Display and set how many colors you can see, execute: (Display newDepth: 8).  (See comment in DisplayMedium)
  21495.     Color is represented as the amount of light in red, green, and blue.  White is (1.0, 1.0, 1.0) and black is (0, 0, 0).  Pure red is (1.0, 0, 0).  These colors are "additive".  Think of Color''s instance variables as:
  21496.     r    amount of red, a Float between 0.0 and 1.0.
  21497.     g    amount of green, a Float between 0.0 and 1.0.
  21498.     b    amount of blue, a Float between 0.0 and 1.0.
  21499. (But, in fact, the three are encoded as values from 0 to 1023 and combined in a single integer, rgb.  The user does not need to know this.)
  21500.     Many colors are named.  You find a color by name by sending a message to class Color, for example (Color lightBlue).  Also, (Color red: 0.2 green: 0.6 blue: 1.0) or (Color r: 0.2 g: 0.6 b: 1.0) creates a color. (see below)
  21501.     A color is essentially immutable.  Once you set red, green, and blue, you cannot change them.  Instead, create a new Color and use it.
  21502.     Applications such as contour maps and bar graphs will want to display one of a set of shades based on a number.  Convert the range of this number to an integer from 1 to N.  Then call (Color green lightShades: N) to get an Array of colors from white to green.  Use the Array messages at:, atPin:, or atWrap: to pull out the correct color from the array.  atPin: gives the first (or last) color if the index is out of range.  atWrap: wraps around to the other end if the index is out of range.
  21503.     Here are some fun things to run in when your screen has color:
  21504.         Pen new mandala: 30 diameter: Display height-100.
  21505.         Pen new web  "Draw with the mouse, opt-click to end"
  21506.         Display fillWhite.  Pen new hilberts: 5.
  21507.         Form toothpaste: 30  "Draw with mouse, opt-click to end"
  21508. You might also want to try the comment in
  21509.     Form>class>examples>tinyText...
  21510.  
  21511.  
  21512. Messages:
  21513.     mixed: proportion with: aColor    Answer this color mixed with the given color additively. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix.
  21514.  
  21515.     +     add two colors
  21516.     -     subtract two colors
  21517.     *    multiply the values of r, g, b by a number or an Array of factors.  ((Color named: #white) * 0.3) gives a darkish gray.  (aColor * #(0 0 0.9)) gives a color with slightly less blue.
  21518.     /    divide a color by a factor or an array of three factors.
  21519.  
  21520.     errorForDepth: d     How close the nearest color at this depth is to this abstract color.  Sum of the squares of the RGB differences, square rooted and normalized to 1.0.  Multiply by 100 to get percent.
  21521.  
  21522.     hue            Returns the hue of the color. On a wheel from 0 to 360 with pure red at 0 and again at 360.
  21523.     saturation    Returns the saturation of the color.  0.0 to 1.0
  21524.     brightness    Returns the brightness of the color.  0.0 to 1.0
  21525.  
  21526.     name    Look to see if this Color has a name.
  21527.     display    Show a swatch of this color tracking the cursor.
  21528.  
  21529.     lightShades: thisMany        An array of thisMany colors from white to the receiver. 
  21530.     darkShades: thisMany        An array of thisMany colors from black to the receiver.  Array is of length num.
  21531.     mix: color2 shades: thisMany        An array of thisMany colors from the receiver to color2.
  21532.     wheel: thisMany            An array of thisMany colors around the color wheel starting and ending at the receiver.
  21533.  
  21534.     pixelValueForDepth: d    Returns the bits that appear be in a Bitmap of this depth for this color.  Represents the nearest available color at this depth.  Normal users do not need to know which pixelValue is used for which color. 
  21535.  
  21536. Messages to Class Color.
  21537.     red: r green: g blue: b        Return a color with the given r, g, and b components.
  21538.     r: g: b:        Same as above, for fast typing.
  21539.  
  21540.      hue: h saturation: s brightness: b        Create a color with the given hue, saturation, and brightness.
  21541.  
  21542.     pink
  21543.      blue
  21544.     red ...    Many colors have messages that return an instance of Color.
  21545.     canUnderstand: #brown      Returns true if #brown is a defined color.
  21546.     names        An OrderedCollection of the names of the colors.
  21547.     named: #notAllThatGray put: aColor    Add a new color to the list and create an access message and a class variable for it.
  21548.     fromUser    Shows the palette of colors available at this display depth.  Click anywhere to return the color you clicked on.
  21549.  
  21550.     hotColdShades: thisMany    An array of thisMany colors showing temperature from blue to red to white hot.
  21551.  
  21552.     stdColorsForDepth: d        An Array of colors available at this depth.  For 16 bit and 32 bits, returns a ColorGenerator.  It responds to at: with a Color for that index, simulating a very big Array. 
  21553.  
  21554.    colorFromPixelValue: value depth: d    Returns a Color whose bit pattern (inside a Bitmap) at this depth is the number specified.  Normal users do not need to use this.
  21555.  
  21556. (See also comments in these classes: Form, Bitmap, BitBlt, Pattern, MaskedForm.)'!
  21557.  
  21558.  
  21559. !Color methodsFor: 'access'!
  21560. alpha
  21561.     "Return the opacity ('alpha') value of opaque so that normal colors can be compared to TransparentColors."
  21562.  
  21563.     ^ 1.0
  21564. ! !
  21565.  
  21566. !Color methodsFor: 'access'!
  21567. blue
  21568.     "Return the blue component of this color, a float in the range [0.0..1.0]."
  21569.  
  21570.     ^ self privateBlue asFloat / ComponentMax! !
  21571.  
  21572. !Color methodsFor: 'access'!
  21573. brightness
  21574.     "Return the brightness of this color, a float in the range [0.0..1.0]."
  21575.  
  21576.     ^ ((self privateRed max:
  21577.         self privateGreen) max:
  21578.         self privateBlue) asFloat / ComponentMax! !
  21579.  
  21580. !Color methodsFor: 'access'!
  21581. green
  21582.     "Return the green component of this color, a float in the range [0.0..1.0]."
  21583.  
  21584.     ^ self privateGreen asFloat / ComponentMax! !
  21585.  
  21586. !Color methodsFor: 'access'!
  21587. hue
  21588.     "Return the hue of this color, an angle in the range [0.0..360.0]."
  21589.  
  21590.     | r g b max min span h |
  21591.     r _ self privateRed.
  21592.     g _ self privateGreen.
  21593.     b _ self privateBlue. 
  21594.  
  21595.     max _ ((r max: g) max: b).
  21596.     min _ ((r min: g) min: b).
  21597.     span _ (max - min) asFloat.
  21598.     span = 0.0 ifTrue: [ ^ 0.0 ].
  21599.  
  21600.     r = max ifTrue: [
  21601.         h _ ((g - b) asFloat / span) * 60.0.
  21602.     ] ifFalse: [
  21603.         g = max
  21604.             ifTrue: [ h _ 120.0 + (((b - r) asFloat / span) * 60.0). ]
  21605.             ifFalse: [ h _ 240.0 + (((r - g) asFloat / span) * 60.0). ].
  21606.     ].
  21607.  
  21608.     h < 0.0 ifTrue: [ h _ 360.0 + h ].
  21609.     ^ h! !
  21610.  
  21611. !Color methodsFor: 'access'!
  21612. luminance
  21613.     "Return the luminance of this color, a brightness value weighted by the human eye's color sensitivity."
  21614.  
  21615.     ^ ((299 * self privateRed) +
  21616.        (587 * self privateGreen) +
  21617.        (114 * self privateBlue)) / (1000 * ComponentMax)
  21618. ! !
  21619.  
  21620. !Color methodsFor: 'access'!
  21621. red
  21622.     "Return the red component of this color, a float in the range [0.0..1.0]."
  21623.  
  21624.     ^ self privateRed asFloat / ComponentMax! !
  21625.  
  21626. !Color methodsFor: 'access'!
  21627. saturation
  21628.     "Return the saturation of this color, a value between 0.0 and 1.0."
  21629.  
  21630.     | r g b max min |
  21631.     r _ self privateRed.
  21632.     g _ self privateGreen.
  21633.     b _ self privateBlue. 
  21634.  
  21635.     max _ min _ r.
  21636.     g > max ifTrue: [max _ g].
  21637.     b > max ifTrue: [max _ b].
  21638.     g < min ifTrue: [min _ g].
  21639.     b < min ifTrue: [min _ b].
  21640.  
  21641.     max = 0
  21642.         ifTrue: [ ^ 0.0 ]
  21643.         ifFalse: [ ^ (max - min) asFloat / max asFloat ].
  21644. ! !
  21645.  
  21646.  
  21647. !Color methodsFor: 'equality' stamp: 'tk 10/21/97 11:24'!
  21648. = aColor
  21649.     "Return true if the receiver equals the given color. This method handles TranslucentColors, too."
  21650.  
  21651.     aColor isColor ifFalse: [^ false].
  21652.     aColor isOpaqueMask ifTrue: [^ false].
  21653.     aColor isTransparent ifTrue: [^ false].
  21654.     ^ aColor privateRGB = rgb and:
  21655.         [aColor privateAlpha = self privateAlpha]
  21656. ! !
  21657.  
  21658. !Color methodsFor: 'equality'!
  21659. hash
  21660.  
  21661.     ^ rgb! !
  21662.  
  21663.  
  21664. !Color methodsFor: 'queries' stamp: 'sw 4/25/1998 12:51'!
  21665. basicType
  21666.     ^ #color! !
  21667.  
  21668. !Color methodsFor: 'queries'!
  21669. isColor
  21670.  
  21671.     ^ true
  21672. ! !
  21673.  
  21674. !Color methodsFor: 'queries'!
  21675. isOpaqueMask
  21676.  
  21677.     ^ false
  21678. ! !
  21679.  
  21680. !Color methodsFor: 'queries'!
  21681. isTransparent
  21682.  
  21683.     ^ false
  21684. ! !
  21685.  
  21686.  
  21687. !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:05'!
  21688. * aNumber
  21689.     "Answer this color with its RGB multiplied by the given number. "
  21690.     "(Color brown * 2) display"
  21691.  
  21692.     ^ Color basicNew
  21693.         setPrivateRed: (self privateRed * aNumber) asInteger
  21694.         green: (self privateGreen * aNumber) asInteger
  21695.         blue: (self privateBlue * aNumber) asInteger
  21696. ! !
  21697.  
  21698. !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:05'!
  21699. + aColor
  21700.     "Answer this color mixed with the given color in an additive color space.  "
  21701.     "(Color blue + Color green) display"
  21702.  
  21703.     ^ Color basicNew
  21704.         setPrivateRed: self privateRed + aColor privateRed
  21705.         green: self privateGreen + aColor privateGreen
  21706.         blue: self privateBlue + aColor  privateBlue
  21707. ! !
  21708.  
  21709. !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:05'!
  21710. - aColor
  21711.     "Answer aColor is subtracted from the given color in an additive color space.  "
  21712.     "(Color white - Color red) display"
  21713.  
  21714.     ^ Color basicNew
  21715.         setPrivateRed: self privateRed - aColor privateRed
  21716.         green: self privateGreen - aColor privateGreen
  21717.         blue: self privateBlue - aColor  privateBlue
  21718. ! !
  21719.  
  21720. !Color methodsFor: 'transformations' stamp: 'di 11/2/97 14:07'!
  21721. / aNumber
  21722.     "Answer this color with its RGB divided by the given number. "
  21723.     "(Color red / 2) display"
  21724.  
  21725.     ^ Color basicNew
  21726.         setPrivateRed: (self privateRed / aNumber) asInteger
  21727.         green: (self privateGreen / aNumber) asInteger
  21728.         blue: (self privateBlue / aNumber) asInteger
  21729. ! !
  21730.  
  21731. !Color methodsFor: 'transformations'!
  21732. alpha: alphaValue
  21733.     "Return a new TransparentColor with the given amount of opacity ('alpha')."
  21734.  
  21735.     ^ TranslucentColor basicNew setRgb: rgb alpha: alphaValue
  21736. ! !
  21737.  
  21738. !Color methodsFor: 'transformations' stamp: 'di 5/15/1998 21:54'!
  21739. dansDarker
  21740.     "Return a darker shade of the same color.
  21741.     An attempt to do better than the current darker method."
  21742.     ^ Color h: self hue s: self saturation
  21743.         v: (self brightness - 0.16 max: 0.0)! !
  21744.  
  21745. !Color methodsFor: 'transformations'!
  21746. darker
  21747.     "Return a lighter shade of the same color.  1/6th towards white. 6/18/96 tk  Should this be an absolute step, instead of relative?"
  21748.     ^ self mixed: 5/6 with: Color black! !
  21749.  
  21750. !Color methodsFor: 'transformations'!
  21751. lighter
  21752.     "Return a lighter shade of the same color.  1/6th towards white. 6/18/96 tk  Should this be an absolute step, instead of relative?"
  21753.     ^ self mixed: 5/6 with: Color white! !
  21754.  
  21755. !Color methodsFor: 'transformations'!
  21756. mixed: proportion with: aColor
  21757.     "Answer this color mixed with the given color. The proportion, a number between 0.0 and 1.0, determines what what fraction of the receiver to use in the mix. For example, 0.9 would yield a color close to the receiver."
  21758.     "Details: This method uses RGB interpolation; HSV interpolation can lead to surprises."
  21759.  
  21760.     | frac1 frac2 |
  21761.     frac1 _ proportion asFloat min: 1.0 max: 0.0.
  21762.     frac2 _ 1.0 - frac1.
  21763.     ^ Color
  21764.         r: (self    red * frac1) + (aColor    red * frac2) 
  21765.         g: (self green * frac1) + (aColor green * frac2) 
  21766.         b: (self   blue * frac1) + (aColor  blue * frac2)
  21767. ! !
  21768.  
  21769. !Color methodsFor: 'transformations' stamp: 'jm 9/22/97 15:11'!
  21770. muchLighter
  21771.  
  21772.     ^ self mixed: 0.233 with: Color white
  21773. ! !
  21774.  
  21775. !Color methodsFor: 'transformations' stamp: 'sw 4/23/1998 18:17'!
  21776. veryMuchLighter
  21777.  
  21778.     ^ self mixed: 0.1165 with: Color white
  21779. ! !
  21780.  
  21781.  
  21782. !Color methodsFor: 'groups of shades' stamp: 'tk 6/18/96'!
  21783. darkShades: thisMany
  21784.     "An array of thisMany colors from black to the receiver.  Array is of length num. Very useful for displaying color based on a variable in your program.  "
  21785.     "Color showColors: (Color red darkShades: 12)"
  21786.  
  21787.     ^ self class black mix: self shades: thisMany
  21788. ! !
  21789.  
  21790. !Color methodsFor: 'groups of shades' stamp: 'tk 6/18/96'!
  21791. lightShades: thisMany
  21792.     "An array of thisMany colors from white to self. Very useful for displaying color based on a variable in your program.  "
  21793.     "Color showColors: (Color red lightShades: 12)"
  21794.  
  21795.     ^ self class white mix: self shades: thisMany
  21796. ! !
  21797.  
  21798. !Color methodsFor: 'groups of shades' stamp: 'tk 6/18/96'!
  21799. mix: color2 shades: thisMany
  21800.     "Return an array of thisMany colors from self to color2. Very useful for displaying color based on a variable in your program.  "
  21801.     "Color showColors: (Color red mix: Color green shades: 12)"
  21802.  
  21803.     | redInc greenInc blueInc rr gg bb c out |
  21804.     thisMany = 1 ifTrue: [^ Array with: color2].
  21805.     redInc _ color2 red - self red / (thisMany-1).
  21806.     greenInc _ color2 green - self green / (thisMany-1).
  21807.     blueInc _ color2 blue - self blue / (thisMany-1).
  21808.     rr _ self red.  gg _ self green.  bb _ self blue.
  21809.     out _ (1 to: thisMany) collect: [:num |
  21810.         c _ Color r: rr g: gg b: bb.
  21811.         rr _ rr + redInc.
  21812.         gg _ gg + greenInc.
  21813.         bb _ bb + blueInc.
  21814.         c].
  21815.     out at: out size put: color2.    "hide roundoff errors"
  21816.     ^ out
  21817. ! !
  21818.  
  21819. !Color methodsFor: 'groups of shades' stamp: 'tk 6/18/96'!
  21820. wheel: thisMany
  21821.     "An array of thisMany colors around the color wheel starting at self and ending all the way around the hue space just before self.  Array is of length thisMany.  Very useful for displaying color based on a variable in your program.  "
  21822.  
  21823.     | sat bri hue step c |
  21824.     thisMany = 1 ifTrue: [^ Array with: self].
  21825.     sat _ self saturation.
  21826.     bri _ self brightness.
  21827.     hue _ self hue.
  21828.     step _ 360.0 / thisMany.
  21829.     ^ (1 to: thisMany) collect: [:num |
  21830.         c _ Color h: hue s: sat v: bri.  "hue is taken mod 360"
  21831.         hue _ hue + step.
  21832.         c].
  21833. ! !
  21834.  
  21835.  
  21836. !Color methodsFor: 'printing'!
  21837. printOn: aStream
  21838.  
  21839.     self storeOn: aStream.
  21840. ! !
  21841.  
  21842. !Color methodsFor: 'printing'!
  21843. shortPrintString
  21844.     "Return a short (but less precise) print string for use where space is tight."
  21845.  
  21846.     | s |
  21847.     s _ WriteStream on: ''.
  21848.     s
  21849.         nextPutAll: '(' , self class name;
  21850.         nextPutAll: ' r: ';
  21851.         nextPutAll: (self red roundTo: 0.01) printString;
  21852.         nextPutAll: ' g: ';
  21853.         nextPutAll: (self green roundTo: 0.01) printString;
  21854.         nextPutAll: ' b: ';
  21855.         nextPutAll: (self blue roundTo: 0.01) printString;
  21856.         nextPutAll: ')'.
  21857.     ^ s contents
  21858. ! !
  21859.  
  21860. !Color methodsFor: 'printing'!
  21861. storeOn: aStream
  21862.  
  21863.     aStream
  21864.         nextPutAll: '(' , self class name;
  21865.         nextPutAll: ' r: ';
  21866.         nextPutAll: (self red roundTo: 0.001) printString;
  21867.         nextPutAll: ' g: ';
  21868.         nextPutAll: (self green roundTo: 0.001) printString;
  21869.         nextPutAll: ' b: ';
  21870.         nextPutAll: (self blue roundTo: 0.001) printString;
  21871.         nextPutAll: ')'.
  21872. ! !
  21873.  
  21874.  
  21875. !Color methodsFor: 'other' stamp: 'sw 2/16/98 03:42'!
  21876. colorForInsets
  21877.     ^ self! !
  21878.  
  21879. !Color methodsFor: 'other' stamp: 'tk 6/14/96'!
  21880. display
  21881.     "Show a swatch of this color tracking the cursor until the next mouseClick. "
  21882.     "Color red display"
  21883.     | f |
  21884.     f _ Form extent: 40@20 depth: Display depth.
  21885.     f fillColor: self.
  21886.     Cursor blank showWhile:
  21887.         [f follow: [Sensor cursorPoint] while: [Sensor noButtonPressed]]! !
  21888.  
  21889. !Color methodsFor: 'other' stamp: 'jm 12/4/97 10:24'!
  21890. name
  21891.     "Return this color's name, or nil if it has no name. Only returns a name if it exactly matches the named color."
  21892.  
  21893.     ColorNames do:
  21894.         [:name | (Color perform: name) = self ifTrue: [^ name]].
  21895.     ^ nil
  21896. ! !
  21897.  
  21898. !Color methodsFor: 'other' stamp: 'sw 9/17/97 17:27'!
  21899. newTileMorphRepresentative
  21900.     ^ ColorTileMorph new! !
  21901.  
  21902. !Color methodsFor: 'other' stamp: 'jm 12/4/97 10:27'!
  21903. rgbTriplet
  21904.     "Color fromUser rgbTriplet"
  21905.  
  21906.     ^ Array
  21907.         with: (self red roundTo: 0.01)
  21908.         with: (self green roundTo: 0.01)
  21909.         with: (self blue roundTo: 0.01)
  21910. ! !
  21911.  
  21912.  
  21913. !Color methodsFor: 'conversions' stamp: 'di 11/3/97 08:40'!
  21914. balancedPatternForDepth: depth
  21915.     "A generalization of bitPatternForDepth: as it exists.  Generates a 2x2 stipple of color.
  21916.     The topLeft and bottomRight pixel are closest approx to this color"
  21917.     | pv1 pv2 mask1 mask2 pv3 c |
  21918.     depth == cachedDepth ifTrue: [^ cachedBitPattern].
  21919.     (depth between: 4 and: 16) ifFalse: [^ self bitPatternForDepth: depth].
  21920.     cachedDepth _ depth.
  21921.     pv1 _ self pixelValueForDepth: depth.
  21922. "
  21923.     Subtract error due to pv1 to get pv2.
  21924.     pv2 _ (self - (err1 _ (Color colorFromPixelValue: pv1 depth: depth) - self))
  21925.                         pixelValueForDepth: depth.
  21926.     Subtract error due to 2 pv1's and pv2 to get pv3.
  21927.     pv3 _ (self - err1 - err1 - ((Color colorFromPixelValue: pv2 depth: depth) - self))
  21928.                         pixelValueForDepth: depth.
  21929. "
  21930.     "Above two statements computed faster by the following..."
  21931.     pv2 _ (c _ self - ((Color colorFromPixelValue: pv1 depth: depth) - self))
  21932.                         pixelValueForDepth: depth.
  21933.     pv3 _ (c + (c - (Color colorFromPixelValue: pv2 depth: depth)))
  21934.                         pixelValueForDepth: depth.
  21935.  
  21936.     "Return to a 2-word bitmap that encodes a 2x2 stipple of the given pixelValues."
  21937.     mask1 _ (#(- - -    
  21938.             16r01010101 - - -            "replicates every other 4 bits"
  21939.             16r00010001 - - - - - - -    "replicates every other 8 bits"
  21940.             16r00000001) at: depth).    "replicates every other 16 bits"
  21941.     mask2 _ (#(- - -    
  21942.             16r10101010 - - -            "replicates the other 4 bits"
  21943.             16r01000100 - - - - - - -    "replicates the other 8 bits"
  21944.             16r00010000) at: depth).    "replicates the other 16 bits"
  21945.     ^ Bitmap with: (mask1*pv1) + (mask2*pv2) with: (mask1*pv3) + (mask2*pv1)! !
  21946.  
  21947. !Color methodsFor: 'conversions' stamp: 'tk 6/14/96'!
  21948. bitPatternForDepth: depth
  21949.     "Return a Bitmap, possibly containing a stipple pattern, that best represents this color at the given depth. BitBlt calls this method to convert colors into Bitmaps. The resulting Bitmap may be multiple words to represent a stipple pattern of several lines.  "
  21950.     "See also:    pixelValueAtDepth:    -- value for single pixel
  21951.                 pixelWordAtDepth:    -- a 32-bit word filled with the pixel value"
  21952.     "Details: The pattern for the most recently requested depth is cached."
  21953.  
  21954.     depth == cachedDepth ifTrue: [^ cachedBitPattern].
  21955.     cachedDepth _ depth.
  21956.  
  21957.     depth > 2 ifTrue: [^ cachedBitPattern _ Bitmap with: (self pixelWordForDepth: depth)].
  21958.     depth = 1 ifTrue: [^ cachedBitPattern _ self halfTonePattern1].
  21959.     depth = 2 ifTrue: [^ cachedBitPattern _ self halfTonePattern2].
  21960. ! !
  21961.  
  21962. !Color methodsFor: 'conversions'!
  21963. closestPixelValue1
  21964.     "Return the nearest approximation to this color for a monochrome Form."
  21965.  
  21966.     "fast special cases"
  21967.     rgb = 0 ifTrue: [^ 1].  "black"
  21968.     rgb = 16r3FFFFFFF ifTrue: [^ 0].  "white"
  21969.  
  21970.     self luminance > 0.5
  21971.         ifTrue: [^ 0]  "white"
  21972.         ifFalse: [^ 1].  "black"
  21973. ! !
  21974.  
  21975. !Color methodsFor: 'conversions'!
  21976. closestPixelValue2
  21977.     "Return the nearest approximation to this color for a 2-bit deep Form."
  21978.  
  21979.     | lum |
  21980.     "fast special cases"
  21981.     rgb = 0 ifTrue: [^ 1].  "black"
  21982.     rgb = 16r3FFFFFFF ifTrue: [^ 2].  "opaque white"
  21983.  
  21984.     lum _ self luminance.
  21985.     lum < 0.2 ifTrue: [^ 1].  "black"
  21986.     lum > 0.6 ifTrue: [^ 2].  "opaque white"
  21987.     ^ 3  "50% gray"
  21988. ! !
  21989.  
  21990. !Color methodsFor: 'conversions'!
  21991. closestPixelValue4
  21992.     "Return the nearest approximation to this color for a 4-bit deep Form."
  21993.  
  21994.     | bIndex |
  21995.     "fast special cases"
  21996.     rgb = 0 ifTrue: [^ 1].  "black"
  21997.     rgb = 16r3FFFFFFF ifTrue: [^ 2].  "opaque white"
  21998.  
  21999.     rgb = PureRed privateRGB ifTrue: [^ 4].
  22000.     rgb = PureGreen privateRGB ifTrue: [^ 5].
  22001.     rgb = PureBlue privateRGB ifTrue: [^ 6].
  22002.     rgb = PureCyan privateRGB ifTrue: [^ 7].
  22003.     rgb = PureYellow privateRGB ifTrue: [^ 8].
  22004.     rgb = PureMagenta privateRGB ifTrue: [^ 9].
  22005.  
  22006.     bIndex _ (self luminance * 8.0) rounded.  "bIndex in [0..8]"
  22007.     ^ #(
  22008.         1    "black"
  22009.         10    "1/8 gray"
  22010.         11    "2/8 gray"
  22011.         12    "3/8 gray"
  22012.         3    "4/8 gray"
  22013.         13    "5/8 gray"
  22014.         14    "6/8 gray"
  22015.         15    "7/8 gray"
  22016.         2    "opaque white"
  22017.     ) at: bIndex + 1.
  22018. ! !
  22019.  
  22020. !Color methodsFor: 'conversions'!
  22021. closestPixelValue8
  22022.     "Return the nearest approximation to this color for an 8-bit deep Form."
  22023.  
  22024.     "fast special cases"
  22025.     rgb = 0 ifTrue: [^ 1].  "black"
  22026.     rgb = 16r3FFFFFFF ifTrue: [^ 255].  "white"
  22027.  
  22028.     self saturation < 0.2 ifTrue: [
  22029.         ^ GrayToIndexMap at: (self privateGreen >> 2) + 1.  "nearest gray"
  22030.     ] ifFalse: [
  22031.         "compute nearest entry in the color cube"
  22032.         ^ 40 +
  22033.           ((((self privateRed * 5) + HalfComponentMask) // ComponentMask) * 36) +
  22034.           ((((self privateBlue * 5) + HalfComponentMask) // ComponentMask) * 6) +
  22035.           (((self privateGreen * 5) + HalfComponentMask) // ComponentMask)].
  22036. ! !
  22037.  
  22038. !Color methodsFor: 'conversions' stamp: 'di 9/2/97 20:21'!
  22039. dominantColor
  22040.     ^ self! !
  22041.  
  22042. !Color methodsFor: 'conversions' stamp: 'di 6/23/97 23:27'!
  22043. halfTonePattern1
  22044.     "Return a halftone-pattern to approximate luminance levels on 1-bit deep Forms."
  22045.  
  22046.     | lum |
  22047.     lum _ self luminance.
  22048.     lum < 0.1 ifTrue: [^ Bitmap with: 16rFFFFFFFF]. "black"
  22049.     lum < 0.4 ifTrue: [^ Bitmap with: 16rBBBBBBBB with: 16rEEEEEEEE]. "dark gray"
  22050.     lum < 0.6 ifTrue: [^ Bitmap with: 16r55555555 with: 16rAAAAAAAA]. "medium gray"
  22051.     lum < 0.9 ifTrue: [^ Bitmap with: 16r44444444 with: 16r11111111]. "light gray"
  22052.     ^ Bitmap with: 0  "1-bit white"
  22053. ! !
  22054.  
  22055. !Color methodsFor: 'conversions'!
  22056. halfTonePattern2
  22057.     "Return a halftone-pattern to approximate luminance levels on 2-bit deep Forms."
  22058.  
  22059.     | lum |
  22060.     lum _ self luminance.
  22061.     lum < 0.125 ifTrue: [^ Bitmap with: 16r55555555].  "black"
  22062.     lum < 0.25 ifTrue: [^ Bitmap with: 16r55555555 with: 16rDDDDDDDD].  "1/8 gray"
  22063.     lum < 0.375 ifTrue: [^ Bitmap with: 16rDDDDDDDD with: 16r77777777].  "2/8 gray"
  22064.     lum < 0.5 ifTrue: [^ Bitmap with: 16rFFFFFFFF with: 16r77777777].  "3/8 gray"
  22065.     lum < 0.625 ifTrue: [^ Bitmap with: 16rFFFFFFFF].  "4/8 gray"
  22066.     lum < 0.75 ifTrue: [^ Bitmap with: 16rFFFFFFFF with: 16rBBBBBBBB].  "5/8 gray"
  22067.     lum < 0.875 ifTrue: [^ Bitmap with: 16rEEEEEEEE with: 16rBBBBBBBB].  "6/8 gray"
  22068.     lum < 1.0 ifTrue: [^ Bitmap with: 16rAAAAAAAA with: 16rBBBBBBBB].  "7/8 gray"
  22069.     ^ Bitmap with: 16rAAAAAAAA  "opaque white"
  22070.  
  22071. "handy expression for computing patterns for 2x2 tiles;
  22072.  set p to a string of 4 letters (e.g., 'wggw' for a gray-and-
  22073.  white checkerboard) and print the result of evaluating:
  22074. | p d w1 w2 |
  22075. p _ 'wggw'.
  22076. d _ Dictionary new.
  22077. d at: $b put: '01'.
  22078. d at: $w put: '10'.
  22079. d at: $g put: '11'.
  22080. w1 _ (d at: (p at: 1)), (d at: (p at: 2)).
  22081. w1 _ '2r', w1, w1, w1, w1, w1, w1, w1, w1, ' hex'.
  22082. w2 _ (d at: (p at: 3)), (d at: (p at: 4)).
  22083. w2 _ '2r', w2, w2, w2, w2, w2, w2, w2, w2, ' hex'.
  22084. Array with: (Compiler evaluate: w1) with: (Compiler evaluate: w2) 
  22085. "! !
  22086.  
  22087. !Color methodsFor: 'conversions' stamp: 'tk 4/24/97'!
  22088. indexInMap: aColorMap
  22089.     "Return the index corresponding to this color in the given color map. RGB colors are truncated to 3-, 4-, or 5-bits per color component when indexing into such a colorMap.  "
  22090.  
  22091.     aColorMap size = 2 ifTrue: [^ (self pixelValueForDepth: 1) + 1].
  22092.     aColorMap size = 4 ifTrue: [^ (self pixelValueForDepth: 2) + 1].
  22093.     aColorMap size = 16 ifTrue: [^ (self pixelValueForDepth: 4) + 1].
  22094.     aColorMap size = 256 ifTrue: [^ (self pixelValueForDepth: 8) + 1].
  22095.     aColorMap size = 512 ifTrue: [^ (self pixelValueForDepth: 9) + 1].
  22096.     aColorMap size = 4096 ifTrue: [^ (self pixelValueForDepth: 12) + 1].
  22097.     aColorMap size = 32768 ifTrue: [^ (self pixelValueForDepth: 16) + 1].
  22098.     self error: 'unknown pixel depth'.
  22099. ! !
  22100.  
  22101. !Color methodsFor: 'conversions'!
  22102. pixelValueForDepth: d
  22103.     "Returns an integer representing the bits that appear in a single pixel of this color in a Form of the given depth. The depth must be one of 1, 2, 4, 8, 16, or 32. Contrast with pixelWordForDepth: and bitPatternForDepth:, which return either a 32-bit word packed with the given pixel value or a multiple-word Bitmap containing a pattern. The inverse is the class message colorFromPixelValue:depth:"
  22104.     "Details: For depths of 8 or less, the result is a colorMap index. For depths of 16 and 32, it is a direct color value with 5 or 8 bits per color component."
  22105.     "Transparency: The pixel value zero is reserved for transparent. For depths greater than 8, black maps to the darkest possible blue."
  22106.  
  22107.     | rgbBlack val |
  22108.     d = 8 ifTrue: [^ self closestPixelValue8].  "common case"
  22109.     d < 8 ifTrue: [
  22110.         d = 4 ifTrue: [^ self closestPixelValue4].
  22111.         d = 2 ifTrue: [^ self closestPixelValue2].
  22112.         d = 1 ifTrue: [^ self closestPixelValue1]].
  22113.  
  22114.     rgbBlack _ 1.  "closest black that is not transparent in RGB"
  22115.  
  22116.     d = 16 ifTrue: [
  22117.         "five bits per component; top bits ignored"
  22118.         val _ (((rgb bitShift: -15) bitAnd: 16r7C00) bitOr:
  22119.              ((rgb bitShift: -10) bitAnd: 16r03E0)) bitOr:
  22120.              ((rgb bitShift: -5) bitAnd: 16r001F).
  22121.         ^ val = 0 ifTrue: [rgbBlack] ifFalse: [val]].
  22122.  
  22123.     d = 32 ifTrue: [
  22124.         "eight bits per component; top 8 bits ignored"
  22125.         val _ (((rgb bitShift: -6) bitAnd: 16rFF0000) bitOr:
  22126.              ((rgb bitShift: -4) bitAnd: 16r00FF00)) bitOr:
  22127.              ((rgb bitShift: -2) bitAnd: 16r0000FF).
  22128.         ^ val = 0 ifTrue: [rgbBlack] ifFalse: [val]].
  22129.  
  22130.     d = 12 ifTrue: [  "for indexing a color map with 4 bits per color component"
  22131.         val _ (((rgb bitShift: -18) bitAnd: 16r0F00) bitOr:
  22132.              ((rgb bitShift: -12) bitAnd: 16r00F0)) bitOr:
  22133.              ((rgb bitShift: -6) bitAnd: 16r000F).
  22134.         ^ val = 0 ifTrue: [rgbBlack] ifFalse: [val]].
  22135.  
  22136.     d = 9 ifTrue: [  "for indexing a color map with 3 bits per color component"
  22137.         val _ (((rgb bitShift: -21) bitAnd: 16r01C0) bitOr:
  22138.              ((rgb bitShift: -14) bitAnd: 16r0038)) bitOr:
  22139.              ((rgb bitShift: -7) bitAnd: 16r0007).
  22140.         ^ val = 0 ifTrue: [rgbBlack] ifFalse: [val]].
  22141.  
  22142.     self error: 'unknown pixel depth: ', d printString
  22143. ! !
  22144.  
  22145. !Color methodsFor: 'conversions'!
  22146. pixelWordFor: depth filledWith: pixelValue
  22147.     "Return to a 32-bit word that concatenates enough copies of the given pixel value to fill the word (i.e., 32/depth copies). Depth should be one of 1, 2, 4, 8, 16, or 32. The pixel value should be an integer in 0..2^depth-1."
  22148.  
  22149.     depth = 32 ifTrue: [^ pixelValue].
  22150.     ^ (pixelValue bitAnd: (1 bitShift: depth) - 1) * 
  22151.         (#(16rFFFFFFFF                "replicates at every bit"
  22152.             16r55555555 -            "replicates every 2 bits"
  22153.             16r11111111 - - -            "replicates every 4 bits"
  22154.             16r01010101 - - - - - - -    "replicates every 8 bits"
  22155.             16r00010001) at: depth)    "replicates every 16 bits"
  22156. ! !
  22157.  
  22158. !Color methodsFor: 'conversions'!
  22159. pixelWordForDepth: depth
  22160.     "Return to a 32-bit word that concatenates enough copies of the receiver's pixel value to fill the word (i.e., 32/depth copies). Depth should be one of 1, 2, 4, 8, 16, or 32. The pixel value should be an integer in 0..2^depth-1."
  22161.  
  22162.     | pixelValue |
  22163.     pixelValue _ self pixelValueForDepth: depth.
  22164.     ^ self pixelWordFor: depth filledWith: pixelValue
  22165. ! !
  22166.  
  22167.  
  22168. !Color methodsFor: 'private'!
  22169. attemptToMutateError
  22170.     "A color is immutable. Once a color's red, green, and blue have been initialized, you cannot change them. Instead, create a new Color and use it."
  22171.  
  22172.     self error: 'Color objects are immutable once created'
  22173. ! !
  22174.  
  22175. !Color methodsFor: 'private'!
  22176. flushCache
  22177.     "Flush my cached bit pattern."
  22178.  
  22179.     cachedDepth _ nil.
  22180.     cachedBitPattern _ nil.
  22181. ! !
  22182.  
  22183. !Color methodsFor: 'private'!
  22184. privateAlpha
  22185.     "Private!! Return the raw alpha value for opaque. Used only for equality testing."
  22186.  
  22187.     ^ 255! !
  22188.  
  22189. !Color methodsFor: 'private'!
  22190. privateBlue
  22191.     "Private!! Return the internal representation of my blue component."
  22192.  
  22193.     ^ rgb bitAnd: ComponentMask! !
  22194.  
  22195. !Color methodsFor: 'private'!
  22196. privateGreen
  22197.     "Private!! Return the internal representation of my green component."
  22198.  
  22199.     ^ (rgb >> GreenShift) bitAnd: ComponentMask! !
  22200.  
  22201. !Color methodsFor: 'private'!
  22202. privateRed
  22203.     "Private!! Return the internal representation of my red component."
  22204.  
  22205.     ^ (rgb bitShift: 0 - RedShift) bitAnd: ComponentMask! !
  22206.  
  22207. !Color methodsFor: 'private'!
  22208. privateRGB
  22209.     "Private!! Return the internal representation of my RGB components."
  22210.  
  22211.     ^ rgb
  22212. ! !
  22213.  
  22214. !Color methodsFor: 'private'!
  22215. setHue: hue saturation: saturation brightness: brightness
  22216.     "Initialize this color to the given hue, saturation, and brightness. See the comment in the instance creation method for details."
  22217.  
  22218.     | s v hf i f p q t | 
  22219.     s _ (saturation asFloat max: 0.0) min: 1.0.
  22220.     v _ (brightness asFloat max: 0.0) min: 1.0.
  22221.  
  22222.     "zero saturation yields gray with the given brightness"
  22223.     s = 0.0 ifTrue: [ ^ self setRed: v green: v blue: v ].
  22224.  
  22225.     hf _ hue asFloat.
  22226.     (hf < 0.0 or: [hf >= 360.0])
  22227.         ifTrue: [hf _ hf - ((hf quo: 360.0) asFloat * 360.0)].
  22228.     hf _ hf / 60.0.
  22229.     i _ hf asInteger.  "integer part of hue"
  22230.     f _ hf fractionPart.         "fractional part of hue"
  22231.     p _ (1.0 - s) * v.
  22232.     q _ (1.0 - (s * f)) * v.
  22233.     t _ (1.0 - (s * (1.0 - f))) * v.
  22234.  
  22235.     0 = i ifTrue: [ ^ self setRed: v green: t blue: p ].
  22236.     1 = i ifTrue: [ ^ self setRed: q green: v blue: p ].
  22237.     2 = i ifTrue: [ ^ self setRed: p green: v blue: t ].
  22238.     3 = i ifTrue: [ ^ self setRed: p green: q blue: v ].
  22239.     4 = i ifTrue: [ ^ self setRed: t green: p blue: v ].
  22240.     5 = i ifTrue: [ ^ self setRed: v green: p blue: q ].
  22241.  
  22242.     self error: 'implementation error'.
  22243. ! !
  22244.  
  22245. !Color methodsFor: 'private' stamp: 'di 11/2/97 12:19'!
  22246. setPrivateRed: r green: g blue: b
  22247.     "Initialize this color's r, g, and b components to the given values in the range [0..ComponentMax].  Encoded in a single variable as 3 integers in [0..1023]."
  22248.  
  22249.     rgb == nil ifFalse: [self attemptToMutateError].
  22250.     rgb _ ((r min: ComponentMask max: 0) bitShift: RedShift) +
  22251.         ((g min: ComponentMask max: 0) bitShift: GreenShift) +
  22252.          (b min: ComponentMask max: 0).
  22253.     cachedDepth _ nil.
  22254.     cachedBitPattern _ nil.
  22255. ! !
  22256.  
  22257. !Color methodsFor: 'private'!
  22258. setRed: r green: g blue: b
  22259.     "Initialize this color's r, g, and b components to the given values in the range [0.0..1.0].  Encoded in a single variable as 3 integers in [0..1023]."
  22260.  
  22261.     rgb == nil ifFalse: [self attemptToMutateError].
  22262.     rgb _
  22263.         (((r * ComponentMax) rounded bitAnd: ComponentMask) bitShift: RedShift) +
  22264.         (((g * ComponentMax) rounded bitAnd: ComponentMask) bitShift: GreenShift) +
  22265.          ((b * ComponentMax) rounded bitAnd: ComponentMask).
  22266.     cachedDepth _ nil.
  22267.     cachedBitPattern _ nil.
  22268. ! !
  22269.  
  22270. !Color methodsFor: 'private'!
  22271. setRed: r green: g blue: b range: range
  22272.     "Initialize this color's r, g, and b components to the given values in the range [0..r]."
  22273.  
  22274.     rgb == nil ifFalse: [self attemptToMutateError].
  22275.     rgb _
  22276.         ((((r * ComponentMask) // range) bitAnd: ComponentMask) bitShift: RedShift) +
  22277.         ((((g * ComponentMask) // range) bitAnd: ComponentMask) bitShift: GreenShift) +
  22278.          (((b * ComponentMask) // range) bitAnd: ComponentMask).
  22279.     cachedDepth _ nil.
  22280.     cachedBitPattern _ nil.
  22281. ! !
  22282.  
  22283. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  22284.  
  22285. Color class
  22286.     instanceVariableNames: ''!
  22287.  
  22288. !Color class methodsFor: 'instance creation' stamp: 'jm 12/1/97 20:43'!
  22289. colorFromPixelValue: p depth: d
  22290.     "Convert a pixel value for the given display depth into a color."
  22291.     "Details: For depths of 8 or less, the pixel value is simply looked up in a table. For greater depths, the color components are extracted and converted into a color."
  22292.  
  22293.     | r g b alpha |
  22294.     d = 8 ifTrue: [^ IndexedColors at: (p bitAnd: 16rFF) + 1].
  22295.     d = 4 ifTrue: [^ IndexedColors at: (p bitAnd: 16r0F) + 1].
  22296.     d = 2 ifTrue: [^ IndexedColors at: (p bitAnd: 16r03) + 1].
  22297.     d = 1 ifTrue: [^ IndexedColors at: (p bitAnd: 16r01) + 1].
  22298.  
  22299.     (d = 16) | (d = 15) ifTrue: [
  22300.         "five bits per component"
  22301.         r _ (p bitShift: -10) bitAnd: 16r1F.
  22302.         g _ (p bitShift: -5) bitAnd: 16r1F.
  22303.         b _ p bitAnd: 16r1F.
  22304.         ^ Color r: r g: g b: b range: 31].
  22305.  
  22306.     d = 32 ifTrue: [
  22307.         "eight bits per component; 8 bits of alpha"
  22308.         r _ (p bitShift: -16) bitAnd: 16rFF.
  22309.         g _ (p bitShift: -8) bitAnd: 16rFF.
  22310.         b _ p bitAnd: 16rFF.
  22311.         alpha _ p bitShift: -24.
  22312.         alpha > 0
  22313.             ifTrue: [^ (Color r: r g: g b: b range: 255) alpha: (alpha asFloat / 255.0)]
  22314.             ifFalse: [^ (Color r: r g: g b: b range: 255)]].
  22315.  
  22316.     d = 12 ifTrue: [
  22317.         "four bits per component"
  22318.         r _ (p bitShift: -8) bitAnd: 16rF.
  22319.         g _ (p bitShift: -4) bitAnd: 16rF.
  22320.         b _ p bitAnd: 16rF.
  22321.         ^ Color r: r g: g b: b range: 15].
  22322.  
  22323.     d = 9 ifTrue: [
  22324.         "three bits per component"
  22325.         r _ (p bitShift: -6) bitAnd: 16r7.
  22326.         g _ (p bitShift: -3) bitAnd: 16r7.
  22327.         b _ p bitAnd: 16r7.
  22328.         ^ Color r: r g: g b: b range: 7].
  22329.  
  22330.     self error: 'unknown pixel depth: ', d printString
  22331. ! !
  22332.  
  22333. !Color class methodsFor: 'instance creation' stamp: 'sw 8/8/97 22:03'!
  22334. fromRgbTriplet: list
  22335.     ^ self r: list first g: list second b: list last! !
  22336.  
  22337. !Color class methodsFor: 'instance creation' stamp: 'jm 12/4/97 13:05'!
  22338. gray: brightness
  22339.     "Return a gray shade with the given brightness in the range [0.0..1.0]."
  22340.  
  22341.     ^ self basicNew setRed: brightness green: brightness blue: brightness
  22342. ! !
  22343.  
  22344. !Color class methodsFor: 'instance creation'!
  22345. h: hue s: saturation v: brightness
  22346.     "Create a color with the given hue, saturation, and brightness. Hue is given as the angle in degrees of the color on the color circle where red is zero degrees. Saturation and brightness are numbers in [0.0..1.0] where larger values are more saturated or brighter colors. For example, (Color h: 0 s: 1 v: 1) is pure red."
  22347.     "Note: By convention, brightness is abbreviated 'v' to to avoid confusion with blue."
  22348.  
  22349.     ^ self basicNew setHue: hue saturation: saturation brightness: brightness! !
  22350.  
  22351. !Color class methodsFor: 'instance creation'!
  22352. new
  22353.  
  22354.     ^ self r: 0.0 g: 0.0 b: 0.0! !
  22355.  
  22356. !Color class methodsFor: 'instance creation' stamp: 'jm 12/4/97 13:04'!
  22357. r: r g: g b: b
  22358.     "Return a color with the given r, g, and b components in the range [0.0..1.0]."
  22359.  
  22360.     ^ self basicNew setRed: r green: g blue: b
  22361. ! !
  22362.  
  22363. !Color class methodsFor: 'instance creation'!
  22364. r: r g: g b: b alpha: alpha
  22365.  
  22366.     ^ (self r: r g: g b: b) alpha: alpha! !
  22367.  
  22368. !Color class methodsFor: 'instance creation'!
  22369. r: r g: g b: b range: range
  22370.     "Return a color with the given r, g, and b components specified as integers in the range [0..r]. This avoids the floating point arithmetic in the red:green:blue: message and is thus a bit faster for certain applications (such as computing a sequence of colors for a palette)."
  22371.  
  22372.     ^ self basicNew setRed: r green: g blue: b range: range! !
  22373.  
  22374. !Color class methodsFor: 'instance creation'!
  22375. random
  22376.     "Return a random color that isn't too dark or under-saturated."
  22377.  
  22378.     ^ self basicNew
  22379.         setHue: (360.0 * RandomStream next)
  22380.         saturation: (0.3 + (RandomStream next * 0.7))
  22381.         brightness: (0.4 + (RandomStream next * 0.6))! !
  22382.  
  22383.  
  22384. !Color class methodsFor: 'class initialization'!
  22385. initialize
  22386.     "Color initialize"
  22387.  
  22388.     "Details: Externally, the red, green, and blue components of color
  22389.     are floats in the range [0.0..1.0]. Internally, they are represented
  22390.     as integers in the range [0..ComponentMask] packing into a
  22391.     small integer to save space and to allow fast hashing and
  22392.     equality testing.
  22393.  
  22394.     For a general description of color representations for computer
  22395.     graphics, including the relationship between the RGB and HSV
  22396.     color models used here, see Chapter 17 of Foley and van Dam,
  22397.     Fundamentals of Interactive Computer Graphics, Addison-Wesley,
  22398.     1982."
  22399.  
  22400.     ComponentMask _ 1023.
  22401.     HalfComponentMask _ 512.  "used to round up in integer calculations"
  22402.     ComponentMax _ 1023.0.  "a Float used to normalize components"
  22403.     RedShift _ 20.
  22404.     GreenShift _ 10.
  22405.     BlueShift _ 0.
  22406.  
  22407.     PureRed         _ self r: 1 g: 0 b: 0.
  22408.     PureGreen     _ self r: 0 g: 1 b: 0.
  22409.     PureBlue     _ self r: 0 g: 0 b: 1.
  22410.     PureYellow     _ self r: 1 g: 1 b: 0.
  22411.     PureCyan     _ self r: 0 g: 1 b: 1.
  22412.     PureMagenta _ self r: 1 g: 0 b: 1.
  22413.  
  22414.     RandomStream _ Random new.
  22415.  
  22416.     self initializeIndexedColors.
  22417.     self initializeGrayToIndexMap.
  22418.     self initializeNames.
  22419.     self initializeHighLights.
  22420. ! !
  22421.  
  22422. !Color class methodsFor: 'class initialization'!
  22423. initializeGrayToIndexMap
  22424.     "Build an array of gray values available in the 8-bit colormap. This array is indexed by a gray level between black (1) and white (256) and returns the pixel value for the corresponding gray level."
  22425.     "Note: This method must be called after initializeIndexedColors, since it uses IndexedColors."
  22426.     "Color initializeGrayToIndexMap"
  22427.  
  22428.     | grayLevels grayIndices c distToClosest dist indexOfClosest |
  22429.     "record the level and index of each gray in the 8-bit color table"
  22430.     grayLevels _ OrderedCollection new.
  22431.     grayIndices _ OrderedCollection new.
  22432.     "Note: skip the first entry, which is reserved for transparent"
  22433.     2 to: IndexedColors size do: [:i |
  22434.         c _ IndexedColors at: i.
  22435.         c saturation = 0.0 ifTrue: [  "c is a gray"
  22436.             grayLevels add: (c privateBlue) >> 2.  "top 8 bits; R, G, and B are the same"
  22437.             grayIndices add: i - 1]].  "pixel values are zero-based"
  22438.     grayLevels _ grayLevels asArray.
  22439.     grayIndices _ grayIndices asArray.
  22440.  
  22441.     "for each gray level in [0..255], select the closest match"
  22442.     GrayToIndexMap _ ByteArray new: 256.
  22443.     0 to: 255 do: [:level |
  22444.         distToClosest _ 10000.  "greater than distance to any real gray"
  22445.         1 to: grayLevels size do: [:i |
  22446.             dist _ (level - (grayLevels at: i)) abs.
  22447.             dist < distToClosest ifTrue: [
  22448.                 distToClosest _ dist.
  22449.                 indexOfClosest _ grayIndices at: i]].
  22450.         GrayToIndexMap at: (level + 1) put: indexOfClosest].
  22451. ! !
  22452.  
  22453. !Color class methodsFor: 'class initialization' stamp: 'tk 6/22/96'!
  22454. initializeHighLights
  22455.     "Create a set of Bitmaps for quickly reversing areas of the screen without converting colors. "
  22456.     "Color initializeHighLights"
  22457.  
  22458.     | t |
  22459.     t _ Array new: 32.
  22460.     t at: 1 put: (Bitmap with: 16rFFFFFFFF).
  22461.     t at: 2 put: (Bitmap with: 16rFFFFFFFF).
  22462.     t at: 4 put: (Bitmap with: 16r55555555).
  22463.     t at: 8 put: (Bitmap with: 16r7070707).
  22464.     t at: 16 put: (Bitmap with: 16rFFFFFFFF).
  22465.     t at: 32 put: (Bitmap with: 16rFFFFFFFF).
  22466.     HighLightBitmaps _ t.
  22467. ! !
  22468.  
  22469. !Color class methodsFor: 'class initialization'!
  22470. initializeIndexedColors
  22471.     "Build an array of colors corresponding to the fixed colormap used
  22472.      for display depths of 1, 2, 4, or 8 bits."
  22473.     "Color initializeIndexedColors"
  22474.  
  22475.     | a index grayVal |
  22476.     a _ Array new: 256.
  22477.  
  22478.     "1-bit colors (monochrome)"
  22479.     a at: 1 put: (Color r: 1.0 g: 1.0 b: 1.0).        "white or transparent"
  22480.     a at: 2 put: (Color r: 0.0 g: 0.0 b: 0.0).    "black"
  22481.  
  22482.     "additional colors for 2-bit color"
  22483.     a at: 3 put: (Color r: 1.0 g: 1.0 b: 1.0).    "opaque white"
  22484.     a at: 4 put: (Color r: 0.5 g: 0.5 b: 0.5).    "1/2 gray"
  22485.  
  22486.     "additional colors for 4-bit color"
  22487.     a at:  5 put: (Color r: 1.0 g: 0.0 b: 0.0).    "red"
  22488.     a at:  6 put: (Color r: 0.0 g: 1.0 b: 0.0).    "green"
  22489.     a at:  7 put: (Color r: 0.0 g: 0.0 b: 1.0).    "blue"
  22490.     a at:  8 put: (Color r: 0.0 g: 1.0 b: 1.0).    "cyan"
  22491.     a at:  9 put: (Color r: 1.0 g: 1.0 b: 0.0).    "yellow"
  22492.     a at: 10 put: (Color r: 1.0 g: 0.0 b: 1.0).    "magenta"
  22493.  
  22494.     a at: 11 put: (Color r: 0.125 g: 0.125 b: 0.125).        "1/8 gray"
  22495.     a at: 12 put: (Color r: 0.25 g: 0.25 b: 0.25).        "2/8 gray"
  22496.     a at: 13 put: (Color r: 0.375 g: 0.375 b: 0.375).        "3/8 gray"
  22497.     a at: 14 put: (Color r: 0.625 g: 0.625 b: 0.625).        "5/8 gray"
  22498.     a at: 15 put: (Color r: 0.75 g: 0.75 b: 0.75).        "6/8 gray"
  22499.     a at: 16 put: (Color r: 0.875 g: 0.875 b: 0.875).        "7/8 gray"
  22500.  
  22501.     "additional colors for 8-bit color"
  22502.     "24 more shades of gray (1/32 increments but not repeating 1/8 increments)"
  22503.     index _ 17.
  22504.     1 to: 31 do: [:v |
  22505.         (v \\ 4) = 0 ifFalse: [
  22506.             grayVal _ v / 32.0.
  22507.             a at: index put: (Color r: grayVal g: grayVal b: grayVal).
  22508.             index _ index + 1]].
  22509.  
  22510.     "The remainder of color table defines a color cube with six steps
  22511.      for each primary color. Note that the corners of this cube repeat
  22512.      previous colors, but this simplifies the mapping between RGB colors
  22513.      and color map indices. This color cube spans indices 40 through 255
  22514.      (indices 41-256 in this 1-based array)."
  22515.     0 to: 5 do: [:r |
  22516.         0 to: 5 do: [:g |
  22517.             0 to: 5 do: [:b |
  22518.                 index _ 41 + ((36 * r) + (6 * b) + g).
  22519.                 index > 256 ifTrue: [
  22520.                     self error: 'index out of range in color table compuation'].
  22521.                 a at: index put: (Color r: r g: g b: b range: 5)]]].
  22522.  
  22523.     IndexedColors _ a.
  22524. ! !
  22525.  
  22526. !Color class methodsFor: 'class initialization'!
  22527. initializeNames
  22528.     "Name some colors."
  22529.     "Color initializeNames"
  22530.  
  22531.     ColorNames _ OrderedCollection new.
  22532.     self named: #black put: (Color r: 0 g: 0 b: 0).
  22533.     self named: #veryVeryDarkGray put: (Color r: 0.125 g: 0.125 b: 0.125).
  22534.     self named: #veryDarkGray put: (Color r: 0.25 g: 0.25 b: 0.25).
  22535.     self named: #darkGray put: (Color r: 0.375 g: 0.375 b: 0.375).
  22536.     self named: #gray put: (Color r: 0.5 g: 0.5 b: 0.5).
  22537.     self named: #lightGray put: (Color r: 0.625 g: 0.625 b: 0.625).
  22538.     self named: #veryLightGray put: (Color r: 0.75 g: 0.75 b: 0.75).
  22539.     self named: #veryVeryLightGray put: (Color r: 0.875 g: 0.875 b: 0.875).
  22540.     self named: #white put: (Color r: 1.0 g: 1.0 b: 1.0).
  22541.     self named: #red put: (Color r: 1.0 g: 0 b: 0).
  22542.     self named: #yellow put: (Color r: 1.0 g: 1.0 b: 0).
  22543.     self named: #green put: (Color r: 0 g: 1.0 b: 0).
  22544.     self named: #cyan put: (Color r: 0 g: 1.0 b: 1.0).
  22545.     self named: #blue put: (Color r: 0 g: 0 b: 1.0).
  22546.     self named: #magenta put: (Color r: 1.0 g: 0 b: 1.0).
  22547.     self named: #brown put: (Color r: 0.6 g: 0.2 b: 0).
  22548.     self named: #orange put: (Color r: 1.0 g: 0.6 b: 0).
  22549.     self named: #lightRed put: (Color r: 1.0 g: 0.8 b: 0.8).
  22550.     self named: #lightYellow put: (Color r: 1.0 g: 1.0 b: 0.8).
  22551.     self named: #lightGreen put: (Color r: 0.8 g: 1.0 b: 0.6).
  22552.     self named: #lightCyan put: (Color r: 0.4 g: 1.0 b: 1.0).
  22553.     self named: #lightBlue put: (Color r: 0.8 g: 1.0 b: 1.0).
  22554.     self named: #lightMagenta put: (Color r: 1.0 g: 0.8 b: 1.0).
  22555.     self named: #lightBrown put: (Color r: 1.0 g: 0.6 b: 0.2).
  22556.     self named: #lightOrange put: (Color r: 1.0 g: 0.8 b: 0.4).
  22557.     self named: #transparent put: (TransparentColor new).
  22558.     self named: #opaqueMask put: (OpaqueMaskColor new).
  22559. ! !
  22560.  
  22561. !Color class methodsFor: 'class initialization' stamp: 'tk 6/13/96'!
  22562. named: newName put: aColor
  22563.     "Add a new color to the list and create an access message and a class variable for it.  The name should start with a lowercase letter.  (The class variable will start with an uppercase letter.)  (Color colorNames) returns a list of all color names.  "
  22564.     | str cap sym accessor csym |
  22565.     (aColor isKindOf: self) ifFalse: [^ self error: 'not a Color'].
  22566.     str _ newName asString.
  22567.     sym _ str asSymbol.
  22568.     cap _ str capitalized.
  22569.     csym _ cap asSymbol.
  22570.     (self class canUnderstand: sym) ifFalse: [
  22571.         "define access message"
  22572.         accessor _ str, (String with: Character cr with: Character tab),             '^', cap.
  22573.         self class compile: accessor
  22574.             classified: 'named colors'].
  22575.     (self classPool includesKey: csym) ifFalse: [
  22576.         self addClassVarName: cap].
  22577.     (ColorNames includes: sym) ifFalse: [
  22578.         ColorNames add: sym].
  22579.     ^ self classPool at: csym put: aColor! !
  22580.  
  22581.  
  22582. !Color class methodsFor: 'examples'!
  22583. colorRampForDepth: depth extent: aPoint
  22584.     "Returns a form of the given size showing R, G, B, and gray ramps for the given depth. Useful for testing color conversions between different depths."
  22585.     "(Color colorRampForDepth: Display depth extent: 256@80) display"
  22586.     "(Color colorRampForDepth: 32 extent: 256@80) displayOn: Display at: 0@0 rule: Form paint"
  22587.  
  22588.     | f dx dy r |
  22589.     f _ Form extent: aPoint depth: depth.
  22590.     dx _ aPoint x // 256.
  22591.     dy _ aPoint y // 4.
  22592.     0 to: 255 do: [:i |
  22593.         r _ (dx * i)@0 extent: dx@dy.
  22594.         f fill: r fillColor: (Color r: i g: 0 b: 0 range: 255).
  22595.         r _ r translateBy: 0@dy.
  22596.         f fill: r fillColor: (Color r: 0 g: i b: 0 range: 255).
  22597.         r _ r translateBy: 0@dy.
  22598.         f fill: r fillColor: (Color r: 0 g: 0 b: i range: 255).
  22599.         r _ r translateBy: 0@dy.
  22600.         f fill: r fillColor: (Color r: i g: i b: i range: 255)].
  22601.     ^ f
  22602. ! !
  22603.  
  22604. !Color class methodsFor: 'examples' stamp: 'tk 6/19/96'!
  22605. hotColdShades: thisMany
  22606.     "An array of thisMany colors showing temperature from blue to red to white hot.  (Later improve this by swinging in hue.)  "
  22607.     "Color showColors: (Color hotColdShades: 25)"
  22608.  
  22609.     | n s1 s2 s3 s4 s5 |
  22610.     thisMany < 5 ifTrue: [^ self error: 'must be at least 5 shades'].
  22611.     n _ thisMany // 5.
  22612.     s1 _ self white mix: self yellow shades: (thisMany - (n*4)).
  22613.     s2 _ self yellow mix: self red shades: n+1.
  22614.     s2 _ s2 copyFrom: 2 to: n+1.
  22615.     s3 _ self red mix: self green darker shades: n+1.
  22616.     s3 _ s3 copyFrom: 2 to: n+1.
  22617.     s4 _ self green darker mix: self blue shades: n+1.
  22618.     s4 _ s4 copyFrom: 2 to: n+1.
  22619.     s5 _ self blue mix: self black shades: n+1.
  22620.     s5 _ s5 copyFrom: 2 to: n+1.
  22621.     ^ s1, s2, s3, s4, s5
  22622. ! !
  22623.  
  22624. !Color class methodsFor: 'examples'!
  22625. showColorCube
  22626.     "Show a 12x12x12 color cube."
  22627.     "Color showColorCube"
  22628.  
  22629.     0 to: 11 do: [:r |
  22630.         0 to: 11 do: [:g |
  22631.             0 to: 11 do: [:b |    
  22632.                 Display fill: (((r*60) + (b*5)) @ (g*5) extent: 5@5)
  22633.                     fillColor: (Color r: r g: g b: b range: 11)]]].
  22634. ! !
  22635.  
  22636. !Color class methodsFor: 'examples'!
  22637. showColors: colorList
  22638.     "Display the given collection of colors across the top of the Display."
  22639.  
  22640.     | w r |
  22641.     w _ Display width // colorList size.
  22642.     r _ 0@0 extent: w@((w min: 30) max: 10).
  22643.     colorList do: [:c |
  22644.         Display fill: r fillColor: c.
  22645.         r _ r translateBy: w@0].
  22646. ! !
  22647.  
  22648. !Color class methodsFor: 'examples'!
  22649. showHSVPalettes
  22650.     "Shows a palette of hues, varying the saturation and brightness for each one. Best results are with depths 16 and 32."
  22651.     "Color showHSVPalettes"
  22652.  
  22653.     | left top c |
  22654.     left _ top _ 0.
  22655.     0 to: 179 by: 15 do: [:h |
  22656.         0 to: 10 do: [:s |
  22657.             left _ (h * 4) + (s * 4).
  22658.             0 to: 10 do: [:v |
  22659.                 c _ Color h: h s: s asFloat / 10.0 v: v asFloat / 10.0.
  22660.                 top _ (v * 4).
  22661.                 Display fill: (left@top extent: 4@4) fillColor: c.
  22662.  
  22663.                 c _ Color h: h + 180 s: s asFloat / 10.0 v: v asFloat / 10.0.
  22664.                 top _ (v * 4) + 50.
  22665.                 Display fill: (left@top extent: 4@4) fillColor: c]]].
  22666. ! !
  22667.  
  22668. !Color class methodsFor: 'examples'!
  22669. showHuesInteractively
  22670.     "Shows a palette of hues at a (saturation, brightness) point determined by the mouse position. Click the mouse button to exit and return the selected (saturation, brightness) point."
  22671.     "Color showHuesInteractively"
  22672.  
  22673.     | p s v |
  22674.     [Sensor anyButtonPressed] whileFalse: [
  22675.         p _ Sensor cursorPoint.
  22676.         s _ p x asFloat / 300.0.
  22677.         v _ p y asFloat / 300.0.
  22678.         self showColors: (self wheel: 12 saturation: s brightness: v)].
  22679.     ^ (s min: 1.0) @ (v min: 1.0)! !
  22680.  
  22681. !Color class methodsFor: 'examples'!
  22682. wheel: thisMany
  22683.     "Return a collection of thisMany colors evenly spaced around the color wheel."
  22684.     "Color showColors: (Color wheel: 12)"
  22685.  
  22686.     ^ Color wheel: thisMany saturation: 0.9 brightness: 0.7
  22687. ! !
  22688.  
  22689. !Color class methodsFor: 'examples'!
  22690. wheel: thisMany saturation: s brightness: v
  22691.     "Return a collection of thisMany colors evenly spaced around the color wheel, all of the given saturation and brightness."
  22692.     "Color showColors: (Color wheel: 12 saturation: 0.4 brightness: 1.0)"
  22693.     "Color showColors: (Color wheel: 12 saturation: 0.8 brightness: 0.5)"
  22694.  
  22695.     ^ (Color h: 0.0 s: s v: v) wheel: thisMany
  22696. ! !
  22697.  
  22698.  
  22699. !Color class methodsFor: 'named colors'!
  22700. black
  22701.     ^Black! !
  22702.  
  22703. !Color class methodsFor: 'named colors'!
  22704. blue
  22705.     ^Blue! !
  22706.  
  22707. !Color class methodsFor: 'named colors'!
  22708. brown
  22709.     ^Brown! !
  22710.  
  22711. !Color class methodsFor: 'named colors'!
  22712. cyan
  22713.     ^Cyan! !
  22714.  
  22715. !Color class methodsFor: 'named colors'!
  22716. darkGray
  22717.     ^DarkGray! !
  22718.  
  22719. !Color class methodsFor: 'named colors'!
  22720. gray
  22721.     ^Gray! !
  22722.  
  22723. !Color class methodsFor: 'named colors'!
  22724. green
  22725.     ^Green! !
  22726.  
  22727. !Color class methodsFor: 'named colors'!
  22728. lightBlue
  22729.     ^LightBlue! !
  22730.  
  22731. !Color class methodsFor: 'named colors'!
  22732. lightBrown
  22733.     ^LightBrown! !
  22734.  
  22735. !Color class methodsFor: 'named colors'!
  22736. lightCyan
  22737.     ^LightCyan! !
  22738.  
  22739. !Color class methodsFor: 'named colors'!
  22740. lightGray
  22741.     ^LightGray! !
  22742.  
  22743. !Color class methodsFor: 'named colors'!
  22744. lightGreen
  22745.     ^LightGreen! !
  22746.  
  22747. !Color class methodsFor: 'named colors'!
  22748. lightMagenta
  22749.     ^LightMagenta! !
  22750.  
  22751. !Color class methodsFor: 'named colors'!
  22752. lightOrange
  22753.     ^LightOrange! !
  22754.  
  22755. !Color class methodsFor: 'named colors'!
  22756. lightRed
  22757.     ^LightRed! !
  22758.  
  22759. !Color class methodsFor: 'named colors'!
  22760. lightYellow
  22761.     ^LightYellow! !
  22762.  
  22763. !Color class methodsFor: 'named colors'!
  22764. magenta
  22765.     ^Magenta! !
  22766.  
  22767. !Color class methodsFor: 'named colors'!
  22768. opaqueMask
  22769.     ^OpaqueMask! !
  22770.  
  22771. !Color class methodsFor: 'named colors'!
  22772. orange
  22773.     ^Orange! !
  22774.  
  22775. !Color class methodsFor: 'named colors'!
  22776. red
  22777.     ^Red! !
  22778.  
  22779. !Color class methodsFor: 'named colors'!
  22780. transparent
  22781.     ^Transparent! !
  22782.  
  22783. !Color class methodsFor: 'named colors'!
  22784. veryDarkGray
  22785.     ^VeryDarkGray! !
  22786.  
  22787. !Color class methodsFor: 'named colors'!
  22788. veryLightGray
  22789.     ^VeryLightGray! !
  22790.  
  22791. !Color class methodsFor: 'named colors'!
  22792. veryVeryDarkGray
  22793.     ^VeryVeryDarkGray! !
  22794.  
  22795. !Color class methodsFor: 'named colors'!
  22796. veryVeryLightGray
  22797.     ^VeryVeryLightGray! !
  22798.  
  22799. !Color class methodsFor: 'named colors'!
  22800. white
  22801.     ^White! !
  22802.  
  22803. !Color class methodsFor: 'named colors'!
  22804. yellow
  22805.     ^Yellow! !
  22806.  
  22807.  
  22808. !Color class methodsFor: 'colormaps' stamp: 'jm 11/12/97 19:16'!
  22809. cachedColormapFrom: sourceDepth to: destDepth
  22810.     "Return a cached colormap for mapping between the given depths. Always return a real colormap, not nil; this allows the client to get an identity colormap that can then be copied and modified to do color transformations."
  22811.     "Note: This method returns a shared, cached colormap to save time and space. Clients that need to modify a colormap returned by this method should make a copy and modify that!!"
  22812.     "Note: The colormap cache may be cleared by evaluating 'Color shutDown'."
  22813.  
  22814.     | key newMap |
  22815.     key _ sourceDepth@destDepth.
  22816.     CachedColormaps == nil ifTrue: [CachedColormaps _ Dictionary new].
  22817.     ^ CachedColormaps at: key ifAbsent: [
  22818.         newMap _ self computeColormapFrom: sourceDepth to: destDepth.
  22819.         CachedColormaps at: key put: newMap.
  22820.         ((sourceDepth >= 16) and: [destDepth < 16]) ifTrue: [
  22821.             "can use the same map from both 16-bits and 32-bits to a given lesser depth"
  22822.             CachedColormaps at: 16@destDepth put: newMap.
  22823.             CachedColormaps at: 32@destDepth put: newMap].
  22824.         newMap].
  22825. ! !
  22826.  
  22827. !Color class methodsFor: 'colormaps'!
  22828. colorMapIfNeededFrom: sourceDepth to: destDepth
  22829.     "Return a colormap for mapping between the given depths, or nil if no colormap is needed."
  22830.     "Note: This method returns a shared, cached colormap to save time and space. Clients that need to modify a colormap returned by this method should make a copy and modify that!!"
  22831.  
  22832.     sourceDepth = destDepth ifTrue: [^ nil].  "not needed if depths are the same"
  22833.  
  22834.     (sourceDepth >= 16) & (destDepth >= 16) ifTrue: [
  22835.         "mapping is done in BitBlt by zero-filling or truncating each color component"
  22836.         ^ nil].
  22837.  
  22838.     ^ Color cachedColormapFrom: sourceDepth to: destDepth
  22839. ! !
  22840.  
  22841. !Color class methodsFor: 'colormaps' stamp: 'jm 12/5/97 18:27'!
  22842. computeColormapFrom: sourceDepth to: destDepth
  22843.     "Compute a colorMap for translating between the given depths. A colormap is a Bitmap whose entries contain the pixel values for the destination depth. Typical clients use cachedColormapFrom:to: instead."
  22844.  
  22845.     | map |
  22846.     sourceDepth < 16 ifTrue: [
  22847.         "source is 1-, 2-, 4-, or 8-bit indexed color"
  22848.         map _ (IndexedColors copyFrom: 1 to: (1 bitShift: sourceDepth))
  22849.                     collect: [:c | c pixelValueForDepth: destDepth].
  22850.         map _ map as: Bitmap.
  22851.     ] ifFalse: [
  22852.         "source is 16-bit or 32-bit RGB; use colormap with 4 bits per color component"
  22853.         map _ self computeRGBColormapFor: destDepth bitsPerColor: 4].
  22854.  
  22855.     "Note: zero is transparent except when source depth is one-bit deep"
  22856.     sourceDepth > 1 ifTrue: [map at: 1 put: 0].
  22857.     ^ map
  22858. ! !
  22859.  
  22860. !Color class methodsFor: 'colormaps' stamp: 'jm 12/4/97 15:25'!
  22861. computeRGBColormapFor: destDepth bitsPerColor: bitsPerColor
  22862.     "Compute a colorMap for translating from 16-bit or 32-bit RGB color to the given depth, using the given number of of bits per color component."
  22863.  
  22864.     | mask map c |
  22865.     (#(3 4 5) includes: bitsPerColor)
  22866.         ifFalse: [self error: 'BitBlt only supports 3, 4, or 5 bits per color component'].
  22867.     mask _ (1 bitShift: bitsPerColor) - 1.
  22868.     map _ Bitmap new: (1 bitShift: (3 * bitsPerColor)).
  22869.     0 to: map size - 1 do: [:i |
  22870.         c _ Color
  22871.             r: ((i bitShift: 0 - (2 * bitsPerColor)) bitAnd: mask)
  22872.             g: ((i bitShift: 0 - bitsPerColor) bitAnd: mask)
  22873.             b: ((i bitShift: 0) bitAnd: mask)
  22874.             range: mask.
  22875.         map at: i + 1 put: (c pixelValueForDepth: destDepth)].
  22876.  
  22877.     map at: 1 put: (Color transparent pixelWordForDepth: destDepth).  "zero always transparent"
  22878.     ^ map
  22879. ! !
  22880.  
  22881.  
  22882. !Color class methodsFor: 'other'!
  22883. colorNames
  22884.     "Return a collection of color names."
  22885.  
  22886.     ^ ColorNames! !
  22887.  
  22888. !Color class methodsFor: 'other'!
  22889. indexedColors
  22890.  
  22891.     ^ IndexedColors! !
  22892.  
  22893. !Color class methodsFor: 'other'!
  22894. maskingMap: depth
  22895.     "Return a color map that maps all colors except transparent to words of all ones. Used to create a mask for a Form whose transparent pixel value is zero. Cache the most recently used map."
  22896.  
  22897.     | sizeNeeded |
  22898.     depth <= 8
  22899.         ifTrue: [sizeNeeded _ 1 bitShift: depth]
  22900.         ifFalse: [sizeNeeded _ 4096].
  22901.     MaskingMap size = sizeNeeded ifTrue: [^ MaskingMap].
  22902.  
  22903.     MaskingMap _ Bitmap new: sizeNeeded withAll: 16rFFFFFFFF.
  22904.     MaskingMap at: 1 put: 0.  "transparent"
  22905.  
  22906.     ^ MaskingMap
  22907. ! !
  22908.  
  22909. !Color class methodsFor: 'other'!
  22910. pixelScreenForDepth: depth
  22911.     "Return a 50% stipple containing alternating pixels of all-zeros and all-ones to be used as a mask at the given depth."
  22912.  
  22913.     | mask bits |
  22914.     mask _ (1 bitShift: depth) - 1.
  22915.     bits _ 2 * depth.
  22916.     [bits >= 32] whileFalse: [
  22917.         mask _ mask bitOr: (mask bitShift: bits).  "double the length of mask"
  22918.         bits _ bits + bits].
  22919.     ^ Bitmap with: mask with: mask bitInvert32
  22920. ! !
  22921.  
  22922. !Color class methodsFor: 'other'!
  22923. quickHighLight: depth
  22924.     "Quickly return a Bitblt-ready raw colorValue for highlighting areas.  6/22/96 tk"
  22925.  
  22926.     ^ HighLightBitmaps at: depth! !
  22927.  
  22928. !Color class methodsFor: 'other'!
  22929. shutDown
  22930.     "Color shutDown"
  22931.  
  22932.     ColorChart _ nil.        "Palette of colors for the user to pick from"
  22933.     CachedColormaps _ nil.    "Maps to translate between color depths"
  22934.     MaskingMap _ nil.        "Maps all colors except transparent to black for creating a mask"
  22935. ! !
  22936.  
  22937.  
  22938. !Color class methodsFor: 'color from user' stamp: 'jm 12/5/97 18:35'!
  22939. colorPaletteForDepth: depth extent: chartExtent
  22940.     "Display a palette of colors sorted horizontally by hue and vertically by lightness. Useful for eyeballing the color gamut of the display, or for choosing a color interactively."
  22941.     "Note: It is slow to build this palette, so it should be cached for quick access."
  22942.     "(Color colorPaletteForDepth: 16 extent: 190@60) display"
  22943.  
  22944.     | basicHue x y c startHue palette transHt vSteps transCaption grayWidth hSteps |
  22945.     palette _ Form extent: chartExtent depth: depth.
  22946.     transCaption _ "(DisplayText text: 'no color' asText textStyle: (TextConstants at: #ComicPlain)) form storeString"
  22947.         (Form extent: 34@9 depth: 1
  22948.             fromArray: #(0 0 256 0 256 0 3808663859 2147483648 2491688266 2147483648 2491688266 0 2491688266 0 2466486578 0 0 0)
  22949.             offset: 0@0).
  22950.     transHt _ transCaption height.
  22951.     palette fillWhite: (0@0 extent: palette width@transHt).
  22952.     palette fillBlack: (0@transHt extent: palette width@1).
  22953.     transCaption displayOn: palette at: palette boundingBox topCenter - ((transCaption width // 2)@0).
  22954.     grayWidth _ 10.
  22955.     startHue _ 338.0.
  22956.     vSteps _ palette height - transHt // 2.
  22957.     hSteps _ palette width - grayWidth.
  22958.     x _ 0.
  22959.     startHue to: startHue + 360.0 by: 360.0/hSteps do: [:h |
  22960.         basicHue _ Color h: h asFloat s: 1.0 v: 1.0.
  22961.         y _ transHt+1.
  22962.         0 to: vSteps do: [:n |
  22963.              c _ basicHue mixed: (n asFloat / vSteps asFloat) with: Color white.
  22964.             palette fill: (x@y extent: 1@1) fillColor: c.
  22965.             y _ y + 1].
  22966.         1 to: vSteps do: [:n |
  22967.              c _ Color black mixed: (n asFloat / vSteps asFloat) with: basicHue.
  22968.             palette fill: (x@y extent: 1@1) fillColor: c.
  22969.             y _ y + 1].
  22970.         x _ x + 1].
  22971.     y _ transHt + 1.
  22972.     1 to: vSteps * 2 do: [:n |
  22973.          c _ Color black mixed: (n asFloat / (vSteps*2) asFloat) with: Color white.
  22974.         palette fill: (x@y extent: 10@1) fillColor: c.
  22975.         y _ y + 1].
  22976.     ^ palette
  22977. ! !
  22978.  
  22979. !Color class methodsFor: 'color from user' stamp: 'jm 12/4/97 10:32'!
  22980. fromUser
  22981.     "Displays a color palette of colors, waits for a mouse click, and returns the selected color. Any pixel on the Display can be chosen, not just those in the color palette."
  22982.     "Note: Since the color chart is cached, you may need to do 'ColorChart _ nil' after changing the oldColorPaletteForDepth:extent: method."
  22983.     "Color fromUser"
  22984.  
  22985.     | d startPt save tr oldColor c here s |
  22986.     d _ Display depth.
  22987.     ((ColorChart == nil) or: [ColorChart depth ~= Display depth]) 
  22988.         ifTrue: [ColorChart _ self oldColorPaletteForDepth: d extent: (2 * 144)@80].
  22989.     Sensor cursorPoint y < Display center y 
  22990.         ifTrue: [startPt _ 0@(Display boundingBox bottom - ColorChart height)]
  22991.         ifFalse: [startPt _ 0@0].
  22992.  
  22993.     save _ Form fromDisplay: (startPt extent: ColorChart extent).
  22994.     ColorChart displayAt: startPt.
  22995.     tr _ ColorChart extent - (50@19) corner: ColorChart extent.
  22996.     tr _ tr translateBy: startPt.
  22997.  
  22998.     oldColor _ nil.
  22999.     [Sensor anyButtonPressed] whileFalse: [
  23000.         c _ Display colorAt: (here _ Sensor cursorPoint).
  23001.         (tr containsPoint: here)
  23002.             ifFalse: [Display fill: (0@61+startPt extent: 20@19) fillColor: c]
  23003.             ifTrue: [
  23004.                 c _ Color transparent.
  23005.                 Display fill: (0@61+startPt extent: 20@19) fillColor: Color white].
  23006.         c = oldColor ifFalse: [
  23007.             Display fillWhite: (20@61 + startPt extent: 135@19).
  23008.             c isTransparent
  23009.                 ifTrue: [s _ c shortPrintString]
  23010.                 ifFalse: [
  23011.                     s _ c shortPrintString.
  23012.                     s _ s copyFrom: 7 to: s size - 1].
  23013.             s displayAt: 20@61 + startPt.
  23014.             oldColor _ c]].
  23015.     save displayAt: startPt.
  23016.     Sensor waitNoButton.
  23017.     ^ c
  23018. ! !
  23019.  
  23020. !Color class methodsFor: 'color from user' stamp: 'jm 12/5/97 18:34'!
  23021. oldColorPaletteForDepth: depth extent: paletteExtent
  23022.     "Returns a form of the given size showing a color palette for the given depth."
  23023.     "(Color oldColorPaletteForDepth: Display depth extent: 720@100) display"
  23024.  
  23025.     | c p f nSteps rect w h q |
  23026.     f _ Form extent: paletteExtent depth: depth.
  23027.     f fill: f boundingBox fillColor: Color white.
  23028.     nSteps _ depth > 8 ifTrue: [12] ifFalse: [6].
  23029.     w _ paletteExtent x // (nSteps * nSteps).
  23030.     h _ paletteExtent y - 20 // nSteps.
  23031.     0 to: nSteps-1 do: [:r |
  23032.         0 to: nSteps-1 do: [:g |
  23033.             0 to: nSteps-1 do: [:b |
  23034.                 c _ Color r: r g: g b: b range: nSteps - 1.
  23035.                 rect _ ((r * nSteps * w) + (b * w)) @ (g * h) extent: w@(h + 1).
  23036.                 f fill: rect fillColor: c]]].
  23037.     q _ Quadrangle origin: paletteExtent - (50@19) corner: paletteExtent.
  23038.     q displayOn: f.
  23039.     ('Trans.' asParagraph asForm) displayOn: f at: q origin + (9@0) rule: Form paint.
  23040.  
  23041.     w _ ((paletteExtent x - q width - 130) // 64) max: 1.
  23042.     p _ paletteExtent x - q width - (64 * w) - 1 @ (paletteExtent y - 19).
  23043.     0 to: 63 do:
  23044.         [:v | c _ Color r: v g: v b: v range: 63.
  23045.         f fill: ((v * w)@0 + p extent: (w + 1)@19) fillColor: c].
  23046.     ^ f
  23047. ! !
  23048. Form subclass: #ColorForm
  23049.     instanceVariableNames: 'colors cachedDepth cachedColormap '
  23050.     classVariableNames: ''
  23051.     poolDictionaries: ''
  23052.     category: 'Graphics-Display Objects'!
  23053. !ColorForm commentStamp: 'di 5/22/1998 16:32' prior: 0!
  23054. ColorForm is a normal Form plus a color map of up to 2^depth Colors. Typically, one reserves one entry in the color map for transparent. This allows 1, 3, 15, or 255 non-transparent colors in ColorForms of depths 1, 2, 4, and 8 bits per pixel. ColorForms don't support depths greater than 8 bits because that would require excessively large color maps with little real benefit, since 16-bit and 32-bit depths already support thousands and millions of colors.
  23055.  
  23056. ColorForms have several uses:
  23057.   1) Precise colors. You can have up to 256 true colors, instead being limited to the 8-bit color palette.
  23058.   2) Easy transparency. Just store (Color transparent) at the desired position in the color map.
  23059.   3) Cheap color remapping by changing the color map.
  23060.  
  23061. A color map is an Array of up to 2^depth Color objects. A Bitmap colorMap is automatically computed and cached for rapid display. Note that if you change the color map, you must resubmit it via the colors: method to flush this cache.
  23062.  
  23063. ColorForms can be a bit tricky. Note that:
  23064.   a) When you BitBlt from one ColorForm to another, you must remember to copy the color map of the source ColorForm to the destination ColorForm.
  23065.   b) A ColorForm's color map is an array of depth-independent Color objects. BitBlt requires a BitMap of actual pixel values, adjusted to the destination depth. These are different things!! ColorForms automatically maintain a cache of the BitBlt-style color map corresponding to the colors array for the last depth on which the ColorForm was displayed, so there should be little need for clients to work with BitBlt-style color maps.
  23066.   c) The default map for 8 bit depth has black in the first entry, not transparent.  Say (cform colors at: 1 put: Color transparent).
  23067. !
  23068.  
  23069.  
  23070. !ColorForm methodsFor: 'accessing' stamp: 'jm 11/14/97 17:39'!
  23071. colors
  23072.     "Return my color palette."
  23073.  
  23074.     self ensureColorArrayExists.
  23075.     ^ colors
  23076. ! !
  23077.  
  23078. !ColorForm methodsFor: 'accessing'!
  23079. colors: colorList
  23080.     "Set my color palette to the given collection."
  23081.  
  23082.     | colorArray colorCount newColors |
  23083.     colorList ifNil: [
  23084.         colors _ cachedDepth _ cachedColormap _ nil.
  23085.         ^ self].
  23086.  
  23087.     colorArray _ colorList asArray.
  23088.     colorCount _ colorArray size.
  23089.     newColors _ Array new: (1 bitShift: depth).
  23090.     1 to: newColors size do: [:i |
  23091.         i <= colorCount
  23092.             ifTrue: [newColors at: i put: (colorArray at: i)]
  23093.             ifFalse: [newColors at: i put: Color transparent]].
  23094.  
  23095.     colors _ newColors.
  23096.     cachedDepth _ nil.
  23097.     cachedColormap _ nil.
  23098. ! !
  23099.  
  23100.  
  23101. !ColorForm methodsFor: 'displaying'!
  23102. displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: rule fillColor: aForm
  23103.  
  23104.     aDisplayMedium copyBits: self boundingBox
  23105.         from: self
  23106.         at: aDisplayPoint + self offset
  23107.         clippingBox: clipRectangle
  23108.         rule: rule
  23109.         fillColor: aForm
  23110.         map: (self colormapIfNeededForDepth: aDisplayMedium depth).
  23111. ! !
  23112.  
  23113. !ColorForm methodsFor: 'displaying' stamp: 'di 7/17/97 10:04'!
  23114. displayOnPort: port at: location
  23115.  
  23116.     port copyForm: self to: location rule: Form paint! !
  23117.  
  23118.  
  23119. !ColorForm methodsFor: 'pixel accessing' stamp: 'jm 11/14/97 17:25'!
  23120. colorAt: aPoint
  23121.     "Return the color of the pixel at aPoint."
  23122.  
  23123.     ^ self colors at: (self pixelValueAt: aPoint) + 1
  23124. ! !
  23125.  
  23126. !ColorForm methodsFor: 'pixel accessing' stamp: 'jm 11/14/97 17:25'!
  23127. colorAt: aPoint put: aColor
  23128.     "Store the given color into the pixel at aPoint. The given color must match one of the colors in the receiver's colormap."
  23129.  
  23130.     | i |
  23131.     i _ self colors indexOf: aColor
  23132.         ifAbsent: [^ self error: 'trying to use a color that is not in my colormap'].
  23133.     self pixelValueAt: aPoint put: i - 1.
  23134. ! !
  23135.  
  23136. !ColorForm methodsFor: 'pixel accessing' stamp: 'tk 10/21/97 12:27'!
  23137. isTransparentAt: aPoint 
  23138.     "Return true if the receiver is transparent at the given point."
  23139.  
  23140.     ^ (self colorAt: aPoint) isTransparent
  23141. ! !
  23142.  
  23143. !ColorForm methodsFor: 'pixel accessing' stamp: 'jm 11/16/97 10:43'!
  23144. pixelValueAt: aPoint 
  23145.     "Return the raw pixel value at the given point. Typical clients use colorAt: to get a Color."
  23146.     "Details: To get the raw pixel value, be sure the peeker's colorMap is nil."
  23147.  
  23148.     ^ (BitBlt bitPeekerFromForm: self) colorMap: nil; pixelAt: aPoint
  23149. ! !
  23150.  
  23151.  
  23152. !ColorForm methodsFor: 'color manipulation'!
  23153. colormapIfNeededForDepth: destDepth
  23154.     "Return a colormap for displaying the receiver at the given depth, or nil if no colormap is needed."
  23155.  
  23156.     | newMap |
  23157.     colors == nil ifTrue: [
  23158.         "use the standard colormap"
  23159.         ^ Color colorMapIfNeededFrom: depth to: destDepth].
  23160.  
  23161.     destDepth = cachedDepth ifTrue: [^ cachedColormap].
  23162.     newMap _ Bitmap new: colors size.
  23163.     1 to: colors size do: [:i |
  23164.         newMap
  23165.             at: i
  23166.             put: ((colors at: i) pixelValueForDepth: destDepth)].
  23167.  
  23168.     cachedDepth _ destDepth.
  23169.     ^ cachedColormap _ newMap.
  23170. ! !
  23171.  
  23172. !ColorForm methodsFor: 'color manipulation' stamp: 'jm 4/18/98 20:34'!
  23173. colorsUsed
  23174.     "Return a list of the colors actually used by this ColorForm."
  23175.  
  23176.     | myColor list |
  23177.     myColor _ self colors.
  23178.     list _ OrderedCollection new.
  23179.     self tallyPixelValues doWithIndex: [:count :i |
  23180.         count > 0 ifTrue: [list add: (myColor at: i)]].
  23181.     ^ list asArray
  23182. ! !
  23183.  
  23184. !ColorForm methodsFor: 'color manipulation' stamp: 'jm 11/16/97 11:18'!
  23185. ensureTransparentColor
  23186.     "Ensure that the receiver (a) includes Color transparent in its color map and (b) that the entry for Color transparent is the first entry in its color map."
  23187.  
  23188.     | i |
  23189. self error: 'not yet implemented'.
  23190.     (colors includes: Color transparent)
  23191.         ifTrue: [
  23192.             (colors indexOf: Color transparent) = 1 ifTrue: [^ self].
  23193.             "shift the entry for color transparent"]
  23194.         ifFalse: [
  23195.             i _ self unusedColormapEntry.
  23196.             i = 0 ifTrue: [self error: 'no color map entry is available'].
  23197.             colors at: i put: Color transparent.
  23198.             "shift the entry for color transparent"].
  23199. ! !
  23200.  
  23201. !ColorForm methodsFor: 'color manipulation' stamp: 'jm 3/27/98 13:24'!
  23202. readFrom: aBinaryStream
  23203.  
  23204.     self error: 'not yet implemented'.
  23205. ! !
  23206.  
  23207. !ColorForm methodsFor: 'color manipulation' stamp: 'jm 11/16/97 09:08'!
  23208. replaceColor: oldColor with: newColor
  23209.     "Replace all occurances of the given color with the given new color in my color map."
  23210.  
  23211.     self ensureColorArrayExists.
  23212.     1 to: colors size do: [:i | 
  23213.         (colors at: i) = oldColor ifTrue: [colors at: i put: newColor]].
  23214.     self clearColormapCache.
  23215. ! !
  23216.  
  23217. !ColorForm methodsFor: 'color manipulation' stamp: 'tk 3/2/98 15:42'!
  23218. replaceColorAt: aPoint with: newColor
  23219.     "Replace a color map entry with newColor.  The entry replaced is the one used by aPoint.  If there are are two entries in the colorMap for the oldColor, just replace ONE!!!!  There are often two whites or two blacks, and this is what you want, when replacing one."
  23220.  
  23221.     | oldIndex |
  23222.     self ensureColorArrayExists.
  23223.     oldIndex _ self pixelValueAt: aPoint.
  23224.     colors at: oldIndex+1 put: newColor.
  23225.     self clearColormapCache.
  23226. ! !
  23227.  
  23228. !ColorForm methodsFor: 'color manipulation' stamp: 'tk 3/2/98 11:26'!
  23229. transparentAllPixelsLike: aPoint
  23230.     "Make all occurances of the given pixel value transparent.  Very useful when two entries in the colorMap have the same value.  This only changes ONE."
  23231.  
  23232.     self replaceColorAt: aPoint with: Color transparent.
  23233. ! !
  23234.  
  23235. !ColorForm methodsFor: 'color manipulation' stamp: 'tk 3/2/98 11:27'!
  23236. transparentColor: aColor
  23237.     "Make all occurances of the given color transparent.  Note: for colors like black and white, which have two entries in the colorMap, this changes BOTH of them.  Not always what you want."
  23238.  
  23239.     self replaceColor: aColor with: Color transparent.
  23240. ! !
  23241.  
  23242. !ColorForm methodsFor: 'color manipulation'!
  23243. twoToneFromDisplay: aRectangle backgroundColor: bgColor
  23244.     "Copy one-bit deep ColorForm from the Display using a color map that maps all colors except the background color to black. Used for caching the contents of inactive MVC windows."
  23245.  
  23246.     | map |
  23247.     (width = aRectangle width and: [height = aRectangle height])
  23248.         ifFalse: [self setExtent: aRectangle extent depth: depth].
  23249.  
  23250.     "make a color map mapping the background color
  23251.      to zero and all other colors to one"
  23252.     map _ Bitmap new: (1 bitShift: (Display depth min: 9)).
  23253.     1 to: map size do: [:i | map at: i put: 16rFFFFFFFF].
  23254.     map at: (bgColor indexInMap: map) put: 0.
  23255.  
  23256.     (BitBlt toForm: self)
  23257.         destOrigin: 0@0;
  23258.         sourceForm: Display;
  23259.         sourceRect: aRectangle;
  23260.         combinationRule: Form over;
  23261.         colorMap: map;
  23262.         copyBits.
  23263. ! !
  23264.  
  23265.  
  23266. !ColorForm methodsFor: 'copying' stamp: 'tk 2/25/98 11:20'!
  23267. copy: aRect
  23268.      "Return a new ColorForm containing the portion of the receiver delineated by aRect."
  23269.  
  23270.     | newForm |
  23271.     newForm _ self class extent: aRect extent depth: depth.
  23272.     ((BitBlt 
  23273.         destForm: newForm
  23274.         sourceForm: self
  23275.         fillColor: nil
  23276.         combinationRule: Form over
  23277.         destOrigin: 0@0
  23278.         sourceOrigin: aRect origin
  23279.         extent: aRect extent
  23280.         clipRect: newForm boundingBox)
  23281.         colorMap: nil) copyBits.
  23282.     colors ifNotNil: [newForm colors: colors copy].
  23283.     ^ newForm
  23284. ! !
  23285.  
  23286. !ColorForm methodsFor: 'copying' stamp: 'jm 2/27/98 09:38'!
  23287. deepCopy
  23288.  
  23289.     ^ self shallowCopy
  23290.         bits: bits copy;
  23291.         offset: offset copy;
  23292.         colors: colors
  23293. ! !
  23294.  
  23295.  
  23296. !ColorForm methodsFor: 'private' stamp: 'jm 11/16/97 09:07'!
  23297. clearColormapCache
  23298.  
  23299.     cachedDepth _ nil.
  23300.     cachedColormap _ nil.
  23301. ! !
  23302.  
  23303. !ColorForm methodsFor: 'private' stamp: 'jm 11/16/97 09:12'!
  23304. depth: bitsPerPixel
  23305.  
  23306.     bitsPerPixel > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits'].
  23307.     super depth: bitsPerPixel.
  23308. ! !
  23309.  
  23310. !ColorForm methodsFor: 'private' stamp: 'jm 11/16/97 08:37'!
  23311. ensureColorArrayExists
  23312.     "Return my color palette."
  23313.  
  23314.     colors ifNil: [
  23315.         depth > 8 ifTrue: [^ self error: 'ColorForms only support depths up to 8 bits'].
  23316.         self colors: (Color indexedColors copyFrom: 1 to: (1 bitShift: depth))].
  23317. ! !
  23318.  
  23319. !ColorForm methodsFor: 'private' stamp: 'jm 11/16/97 08:37'!
  23320. setExtent: extent depth: bitsPerPixel
  23321.     "Create a virtual bit map with the given extent and bitsPerPixel."
  23322.  
  23323.     bitsPerPixel > 8 ifTrue: [self error: 'ColorForms only support depths up to 8 bits'].
  23324.     super setExtent: extent depth: bitsPerPixel.
  23325. ! !
  23326.  
  23327. !ColorForm methodsFor: 'private' stamp: 'jm 2/24/98 18:53'!
  23328. unusedColormapEntry
  23329.     "Return the index of an unused color map entry, or zero if there isn't one."
  23330.  
  23331.     | tallies |
  23332.     tallies _ self tallyPixelValues.
  23333.     1 to: tallies size do: [:i |
  23334.         (tallies at: i) = 0 ifTrue: [^ i]].
  23335.     ^ 0
  23336. ! !
  23337.  
  23338. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  23339.  
  23340. ColorForm class
  23341.     instanceVariableNames: ''!
  23342.  
  23343. !ColorForm class methodsFor: 'all' stamp: 'jm 11/16/97 09:17'!
  23344. mappingWhiteToTransparentFrom: aFormOrCursor
  23345.     "Return a ColorForm copied from the given Form or Cursor with white mapped to transparent."
  23346.  
  23347.     | f map |
  23348.     aFormOrCursor depth <= 8 ifFalse: [
  23349.         ^ self error: 'argument depth must be 8-bits per pixel or less'].
  23350.     (aFormOrCursor isKindOf: ColorForm) ifTrue: [
  23351.         f _ aFormOrCursor deepCopy.
  23352.         map _ aFormOrCursor colors.
  23353.     ] ifFalse: [
  23354.         f _ ColorForm extent: aFormOrCursor extent depth: aFormOrCursor depth.
  23355.         f copyBits: aFormOrCursor boundingBox
  23356.             from: aFormOrCursor
  23357.             at: 0@0
  23358.             clippingBox: aFormOrCursor boundingBox
  23359.             rule: Form over
  23360.             fillColor: nil.
  23361.         map _ Color indexedColors copyFrom: 1 to: (1 bitShift: aFormOrCursor depth)].
  23362.     map _ map collect: [:c |
  23363.         c = Color white ifTrue: [Color transparent] ifFalse: [c]].
  23364.     f colors: map.
  23365.     ^ f
  23366. ! !
  23367.  
  23368. !ColorForm class methodsFor: 'all'!
  23369. twoToneFromDisplay: aRectangle using: oldForm backgroundColor: bgColor
  23370.     "Return a 1-bit deep ColorForm copied from the given rectangle of the display. All colors except the background color will be mapped to black."
  23371.  
  23372.     | f |
  23373.     ((oldForm ~~ nil) and: [oldForm extent = aRectangle extent]) ifTrue: [
  23374.         f _ oldForm fromDisplay: aRectangle.
  23375.     ] ifFalse: [
  23376.         f _ ColorForm extent: aRectangle extent depth: 1.
  23377.         f twoToneFromDisplay: aRectangle backgroundColor: bgColor.
  23378.         f colors: (Array
  23379.             with: bgColor
  23380.             with: Color black)].
  23381.     ^ f
  23382. ! !
  23383. SketchMorph subclass: #ColorPickerMorph
  23384.     instanceVariableNames: 'selectedColor sourceHand deleteOnMouseUp updateContinuously selector target '
  23385.     classVariableNames: 'ColorChart FeedbackBox TransparentBox '
  23386.     poolDictionaries: ''
  23387.     category: 'Morphic-Widgets'!
  23388.  
  23389. !ColorPickerMorph methodsFor: 'initialization' stamp: 'jm 11/4/97 07:46'!
  23390. initialize
  23391.  
  23392.     super initialize.
  23393.     self form: ColorChart deepCopy.
  23394.     selectedColor _ Color white.
  23395.     sourceHand _ nil.
  23396.     deleteOnMouseUp _ true.
  23397.     updateContinuously _ true.
  23398.     selector _ nil.
  23399.     target _ nil.
  23400. ! !
  23401.  
  23402.  
  23403. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23404. deleteOnMouseUp
  23405.  
  23406.     ^ deleteOnMouseUp
  23407. ! !
  23408.  
  23409. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23410. deleteOnMouseUp: aBoolean
  23411.  
  23412.     deleteOnMouseUp _ aBoolean.
  23413. ! !
  23414.  
  23415. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23416. selectedColor
  23417.  
  23418.     ^ selectedColor
  23419. ! !
  23420.  
  23421. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23422. selector
  23423.  
  23424.     ^ selector
  23425. ! !
  23426.  
  23427. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23428. selector: aSymbol
  23429.  
  23430.     selector _ aSymbol.
  23431. ! !
  23432.  
  23433. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23434. sourceHand
  23435.  
  23436.     ^ sourceHand
  23437. ! !
  23438.  
  23439. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23440. sourceHand: aHand
  23441.  
  23442.     sourceHand _ aHand.
  23443. ! !
  23444.  
  23445. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23446. target
  23447.  
  23448.     ^ target
  23449. ! !
  23450.  
  23451. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:15'!
  23452. target: anObject
  23453.  
  23454.     target _ anObject.
  23455. ! !
  23456.  
  23457. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:46'!
  23458. updateContinuously
  23459.  
  23460.     ^ updateContinuously
  23461. ! !
  23462.  
  23463. !ColorPickerMorph methodsFor: 'accessing' stamp: 'jm 11/4/97 07:46'!
  23464. updateContinuously: aBoolean
  23465.  
  23466.     updateContinuously _ aBoolean.
  23467. ! !
  23468.  
  23469.  
  23470. !ColorPickerMorph methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!
  23471. handlesMouseDown: evt
  23472.  
  23473.     ^ true
  23474. ! !
  23475.  
  23476. !ColorPickerMorph methodsFor: 'event handling' stamp: 'jm 11/4/97 07:15'!
  23477. mouseDown: evt
  23478.  
  23479.     sourceHand _ evt hand.
  23480.     self startStepping.
  23481. ! !
  23482.  
  23483. !ColorPickerMorph methodsFor: 'event handling' stamp: 'jm 11/4/97 07:46'!
  23484. mouseUp: evt
  23485.  
  23486.     self stopStepping.
  23487.     sourceHand _ nil.
  23488.     deleteOnMouseUp ifTrue: [self delete].
  23489.     self updateTargetColor.
  23490. ! !
  23491.  
  23492.  
  23493. !ColorPickerMorph methodsFor: 'stepping' stamp: 'jm 11/4/97 07:15'!
  23494. step
  23495.  
  23496.     sourceHand ifNotNil:
  23497.         [self pickColorAt: sourceHand position].
  23498. ! !
  23499.  
  23500. !ColorPickerMorph methodsFor: 'stepping' stamp: 'jm 11/4/97 07:15'!
  23501. stepTime
  23502.  
  23503.     ^ 50
  23504. ! !
  23505.  
  23506.  
  23507. !ColorPickerMorph methodsFor: 'private' stamp: 'jm 11/4/97 07:15'!
  23508. pickColorAt: aPoint
  23509.  
  23510.     | worldBox globalP c |
  23511.     (FeedbackBox containsPoint: aPoint - self topLeft) ifTrue: [^ self].  "do nothing"
  23512.  
  23513.     "pick up color, either inside or outside this world"
  23514.     worldBox _ self world viewBox.
  23515.     globalP _ aPoint + worldBox topLeft.  "get point in screen coordinates"
  23516.     (worldBox containsPoint: globalP)
  23517.         ifTrue: [c _ self world colorAt: aPoint belowMorph: Morph new]
  23518.         ifFalse: [c _ Display colorAt: globalP].
  23519.  
  23520.     "check for transparent color and update using appropriate feedback color"
  23521.     (TransparentBox containsPoint: aPoint - self topLeft)
  23522.         ifTrue: [self updateColor: Color transparent feedbackColor: Color white]
  23523.         ifFalse: [self updateColor: c feedbackColor: c].
  23524. ! !
  23525.  
  23526. !ColorPickerMorph methodsFor: 'private' stamp: 'jm 11/4/97 07:46'!
  23527. updateColor: aColor feedbackColor: feedbackColor
  23528.     "Set my selected color to the given color if it is different. Give user feedback. Inform the target of the change if the target and selector are not nil." 
  23529.  
  23530.     selectedColor = aColor ifTrue: [^ self].  "do nothing if color doesn't change"
  23531.  
  23532.     originalForm fill: FeedbackBox fillColor: feedbackColor.
  23533.     self form: originalForm.
  23534.     selectedColor _ aColor.
  23535.     updateContinuously ifTrue: [self updateTargetColor].
  23536. ! !
  23537.  
  23538. !ColorPickerMorph methodsFor: 'private' stamp: 'jm 11/4/97 07:46'!
  23539. updateTargetColor
  23540.  
  23541.     ((target ~~ nil) and: [selector ~~ nil]) ifTrue: [
  23542.         selector numArgs = 2
  23543.             ifTrue: [target perform: selector with: selectedColor with: sourceHand]
  23544.             ifFalse: [target perform: selector with: selectedColor]].
  23545. ! !
  23546.  
  23547.  
  23548. !ColorPickerMorph methodsFor: 'menu' stamp: 'jm 11/4/97 07:46'!
  23549. addCustomMenuItems: aCustomMenu hand: aHandMorph
  23550.  
  23551.     super addCustomMenuItems: aCustomMenu hand: aHandMorph.
  23552.     deleteOnMouseUp
  23553.         ifTrue: [aCustomMenu add: 'stay up' action: #toggleDeleteOnMouseUp]
  23554.         ifFalse: [aCustomMenu add: 'do not stay up' action: #toggleDeleteOnMouseUp].
  23555.     updateContinuously
  23556.         ifTrue: [aCustomMenu add: 'update only at end' action: #toggleUpdateContinuously]
  23557.         ifFalse: [aCustomMenu add: 'update continuously' action: #toggleUpdateContinuously].
  23558. ! !
  23559.  
  23560. !ColorPickerMorph methodsFor: 'menu' stamp: 'jm 11/4/97 07:46'!
  23561. toggleDeleteOnMouseUp
  23562.  
  23563.     deleteOnMouseUp _ deleteOnMouseUp not.
  23564. ! !
  23565.  
  23566. !ColorPickerMorph methodsFor: 'menu' stamp: 'jm 11/4/97 07:46'!
  23567. toggleUpdateContinuously
  23568.  
  23569.     updateContinuously _ updateContinuously not.
  23570. ! !
  23571.  
  23572. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  23573.  
  23574. ColorPickerMorph class
  23575.     instanceVariableNames: ''!
  23576.  
  23577. !ColorPickerMorph class methodsFor: 'all' stamp: 'jm 5/13/1998 14:44'!
  23578. initialize
  23579.     "ColorPickerMorph initialize"
  23580.  
  23581.     ColorChart _ Color colorPaletteForDepth: 16 extent: 190@60.
  23582.     TransparentBox _ ColorChart boundingBox withHeight: 10.
  23583.     FeedbackBox _ (ColorChart width - 20)@0 extent: 20@9.
  23584. ! !
  23585. ColorTileMorph subclass: #ColorSeerTile
  23586.     instanceVariableNames: ''
  23587.     classVariableNames: ''
  23588.     poolDictionaries: ''
  23589.     category: 'Morphic-Scripting-Tiles'!
  23590.  
  23591. !ColorSeerTile methodsFor: 'as yet unclassified' stamp: 'sw 5/2/1998 15:00'!
  23592. initialize
  23593.  
  23594.     | m1 m2 desiredW |
  23595.     super initialize.
  23596.     self removeAllMorphs.    "get rid of the parts of a regular Color tile"
  23597.     type _ #operator.
  23598.     operatorOrExpression _ #color:sees:.
  23599.     m1 _ StringMorph new initWithContents: 'color    sees' font: ScriptingSystem fontForTiles.
  23600.     m2 _ Morph new extent: 12@8; color: (Color r: 0.8 g: 0 b: 0).
  23601.     desiredW _ m1 width + 6.
  23602.     self extent: (desiredW max: self class defaultW) @ self class defaultH.
  23603.     m1 position: (bounds center x - (m1 width // 2)) @ (bounds top + 5).
  23604.     m2 position: (bounds center x - (m2 width // 2) + 3) @ (bounds top + 8).
  23605.     self addMorph: m1; addMorphFront: m2.
  23606.     colorSwatch _ m2.
  23607.     ! !
  23608.  
  23609. !ColorSeerTile methodsFor: 'as yet unclassified' stamp: 'tk 12/2/97 13:12'!
  23610. storeCodeOn: aStream
  23611.     "We have a hidden arg.  Give 'keyword1: arg1 keyword2:' as my operator string" 
  23612.     
  23613.     | parts |
  23614.     parts _ operatorOrExpression keywords.    "color:sees:"
  23615.     ^ aStream nextPutAll: (parts at: 1); space;
  23616.         nextPutAll: colorSwatch color printString; space;
  23617.         nextPutAll: (parts at: 2).
  23618.     
  23619. ! !
  23620.  
  23621. !ColorSeerTile methodsFor: 'as yet unclassified' stamp: 'tk 12/3/97 09:51'!
  23622. updateLiteralLabel
  23623.     "Do nothing"! !
  23624. StandardSystemView subclass: #ColorSystemView
  23625.     instanceVariableNames: ''
  23626.     classVariableNames: ''
  23627.     poolDictionaries: ''
  23628.     category: 'Interface-Support'!
  23629.  
  23630. !ColorSystemView methodsFor: 'as yet unclassified'!
  23631. cacheBitsAsTwoTone
  23632.     ^ false! !
  23633.  
  23634. !ColorSystemView methodsFor: 'as yet unclassified' stamp: 'di 2/26/98 08:58'!
  23635. displayDeEmphasized 
  23636.     "Display this view with emphasis off.
  23637.     If windowBits is not nil, then simply BLT if possible."
  23638.     bitsValid
  23639.         ifTrue: [self lock.
  23640.                 windowBits displayAt: self windowOrigin]
  23641.         ifFalse: [super displayDeEmphasized]
  23642. ! !
  23643. TileMorph subclass: #ColorTileMorph
  23644.     instanceVariableNames: 'colorSwatch '
  23645.     classVariableNames: ''
  23646.     poolDictionaries: ''
  23647.     category: 'Morphic-Scripting-Tiles'!
  23648.  
  23649. !ColorTileMorph methodsFor: 'initialization'!
  23650. initialize
  23651.  
  23652.     super initialize.
  23653.     type _ #literal.
  23654.     self addColorSwatch.
  23655. ! !
  23656.  
  23657.  
  23658. !ColorTileMorph methodsFor: 'events'!
  23659. handlesMouseDown: evt
  23660.  
  23661.     (colorSwatch containsPoint: evt cursorPoint)
  23662.         ifTrue: [^ true]
  23663.         ifFalse: [^ super handlesMouseDown: evt].
  23664. ! !
  23665.  
  23666. !ColorTileMorph methodsFor: 'events'!
  23667. mouseDown: evt
  23668.  
  23669.     (colorSwatch containsPoint: evt cursorPoint)
  23670.         ifFalse: [super mouseDown: evt].
  23671. ! !
  23672.  
  23673. !ColorTileMorph methodsFor: 'events' stamp: 'jm 5/13/1998 14:47'!
  23674. mouseUp: evt
  23675.  
  23676.     evt hand changeColorTarget: colorSwatch selector: #color:.
  23677.     self acceptNewLiteral.
  23678. ! !
  23679.  
  23680.  
  23681. !ColorTileMorph methodsFor: 'other' stamp: 'tk 9/17/97 18:13'!
  23682. addColorSwatch
  23683.  
  23684.     | m1 m2 desiredW |
  23685.     m1 _ StringMorph new contents: 'color'.
  23686.     m2 _ Morph new extent: 12@8; color: (Color r: 0.8 g: 0 b: 0).
  23687.     desiredW _ m1 width + 6.
  23688.     self extent: (desiredW max: self class defaultW) @ self class defaultH.
  23689.     m1 position: (bounds center x - (m1 width // 2)) @ (bounds top + 1).
  23690.     m2 position: (bounds center x - (m2 width // 2)) @ (m1 bottom - 1).
  23691.     self addMorph: m1; addMorph: m2.
  23692.     colorSwatch _ m2.
  23693. ! !
  23694.  
  23695. !ColorTileMorph methodsFor: 'other' stamp: 'jm 6/25/97 17:38'!
  23696. resultType
  23697.  
  23698.     ^ #color! !
  23699.  
  23700. !ColorTileMorph methodsFor: 'other'!
  23701. storeCodeOn: aStream
  23702.  
  23703.     aStream nextPutAll: colorSwatch color printString.
  23704. ! !
  23705. AlignmentMorph subclass: #CommandTilesMorph
  23706.     instanceVariableNames: 'morph playerScripted '
  23707.     classVariableNames: ''
  23708.     poolDictionaries: ''
  23709.     category: 'Morphic-Scripting-Tiles'!
  23710. !CommandTilesMorph commentStamp: 'di 5/22/1998 16:32' prior: 0!
  23711. CommandTilesMorph comment:
  23712. 'An entire Smalltalk statement in tiles.  A line of code.'!
  23713.  
  23714.  
  23715. !CommandTilesMorph methodsFor: 'all'!
  23716. initialize
  23717.  
  23718.     super initialize.
  23719.     centering _ #center.
  23720.     hResizing _ #shrinkWrap.
  23721.     borderWidth _ 0.
  23722.     inset _ 0.
  23723.     self extent: 5@5.  "will grow to fit"
  23724. ! !
  23725.  
  23726. !CommandTilesMorph methodsFor: 'all' stamp: 'tk 10/1/97 18:25'!
  23727. isTileLike
  23728.     "Can be dropped into a script"
  23729.     ^ true! !
  23730.  
  23731. !CommandTilesMorph methodsFor: 'all' stamp: 'sw 1/29/98 18:32'!
  23732. setMorph: aMorph
  23733.     playerScripted _ aMorph playerScripted
  23734. ! !
  23735.  
  23736. !CommandTilesMorph methodsFor: 'all'!
  23737. tileRows
  23738.  
  23739.     ^ Array with: self submorphs! !
  23740. Object subclass: #Comment
  23741.     instanceVariableNames: ''
  23742.     classVariableNames: 'CommentsTable '
  23743.     poolDictionaries: ''
  23744.     category: 'PluggableWebServer'!
  23745. !Comment commentStamp: 'di 5/22/1998 16:33' prior: 0!
  23746. A Comment space is like a bulletin board.  It is a web page with a list statements from many different people.  At the bottom there is a form for you to add your own statement.
  23747.  
  23748. Anyone may start a new comment page, just by asking for a page with a new key, and there can be any number of pages.  The default Swiki has a page called 'pws' already created.
  23749.  
  23750. The administrator must take special action to save the accumulated comments (Comment saveTo: 'aFileName').  Comments are not automatically stored on the disk like regular Swiki pages are.  So, for the moment, it is likely that Comments will get lost when the server is restarted.
  23751.  
  23752. URLs are of the form 
  23753. machine:80/Comment.{commentKey}
  23754. machine:80/Comment.{commentKey}.{number}
  23755. machine:80/Comment.{commentKey}.note   -- Does this really work???  -tk
  23756. machine:80/Comment.{commentKey}.gif!
  23757.  
  23758.  
  23759. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  23760.  
  23761. Comment class
  23762.     instanceVariableNames: ''!
  23763.  
  23764. !Comment class methodsFor: 'initialization' stamp: 'mjg 11/10/97 10:44'!
  23765. initialize
  23766.     CommentsTable := Dictionary new.! !
  23767.  
  23768. !Comment class methodsFor: 'initialization' stamp: 'mjg 11/24/97 15:20'!
  23769. readIn: filename
  23770.     |f|
  23771.     f _ ReferenceStream fileNamed: filename.
  23772.     CommentsTable _ f next.
  23773.     f close.! !
  23774.  
  23775. !Comment class methodsFor: 'initialization' stamp: 'mjg 11/24/97 15:20'!
  23776. saveTo: filename
  23777.     |f|
  23778.     f _ ReferenceStream fileNamed: filename.
  23779.     f nextPut: CommentsTable.
  23780.     f close.! !
  23781.  
  23782. !Comment class methodsFor: 'initialization' stamp: 'mjg 11/17/97 14:52'!
  23783. setUpExample
  23784.     | newDiscussion |
  23785.     newDiscussion _ Discussion new.
  23786.     newDiscussion title: 'pws'.
  23787.     newDiscussion description: 'Here is a space for talking about the Pluggable Web Server.'.
  23788.     CommentsTable at: 'pws' put: newDiscussion.
  23789.  
  23790. ! !
  23791.  
  23792.  
  23793. !Comment class methodsFor: 'URL processing' stamp: 'mjg 11/10/97 11:18'!
  23794. comments
  23795.     ^CommentsTable! !
  23796.  
  23797. !Comment class methodsFor: 'URL processing' stamp: 'mjg 12/19/97 13:44'!
  23798. createComment: request
  23799.     "Create a new comment from a Web request"
  23800.     | newNote newMap |
  23801.     request fields isNil ifTrue: [self error: 'No request to create a comment from!!'].
  23802.     newNote := Note new.
  23803.     newMap := URLmap new.
  23804.     newNote author: (request fields at: 'author' ifAbsent: ['Anonymous']).
  23805.     newNote title: (request fields at: 'title' ifAbsent: ['Untitled']).
  23806.     newNote text: (HTMLformatter swikify: 
  23807.         (request fields at: 'text' ifAbsent: ['Nothing much to say'])
  23808.         linkhandler: [:phrase | newMap linkFor: phrase from: (request peerName) 
  23809.             storingTo: OrderedCollection new]).
  23810.     newNote timestamp: (Date today printString),' ',(Time now printString).
  23811.     newNote children: OrderedCollection new. "For later addition of threaded comments"
  23812.     ^newNote
  23813. ! !
  23814.  
  23815. !Comment class methodsFor: 'URL processing' stamp: 'tk 5/6/1998 18:48'!
  23816. process: request 
  23817.     "URLs are of the form Comment.commentKey or 
  23818.     Comment.commentKey.note of Comment.commentKey.gif.
  23819.     
  23820.     If commentKey is accessed but not created, create an empty one.
  23821.     If note is accessed, display it."
  23822.     | commentKey noteIndex newNote |
  23823.     (request message size > 1) ifTrue: [commentKey _ request message at: 2]
  23824.     ifFalse: [commentKey _ 'comment' "Just a default comment space"].
  23825.     (CommentsTable includesKey: commentKey)
  23826.         ifFalse: 
  23827.             [CommentsTable at: commentKey put: Discussion new.
  23828.             (CommentsTable at: commentKey)
  23829.                 title: commentKey.
  23830.             (CommentsTable at: commentKey)
  23831.                 description: 'Discussion on ' , commentKey].
  23832.     request fields isNil
  23833.         ifFalse: 
  23834.             ["Are there input fields?"
  23835.             newNote _ self createComment: request.
  23836.             newNote parent: commentKey.
  23837.             (CommentsTable at: commentKey)
  23838.                 addNote: newNote.
  23839.             newNote url: ('Comment.',commentKey,'.',
  23840.                 (CommentsTable at: commentKey) notes size printString)].
  23841.     request message size > 2
  23842.         ifTrue: 
  23843.             ["There's a note reference or a request for a status image"
  23844.             noteIndex _ request message at: 3.
  23845.             noteIndex asUppercase = 'GIF'
  23846.             ifTrue: [
  23847.             request reply: (PWS success),(PWS content: 'image/gif').
  23848.             request reply: (HTMLformatter textToGIF: 
  23849.                 (CommentsTable at: commentKey) status)]
  23850.             ifFalse: [request reply: (self showNote: ((CommentsTable at: commentKey)
  23851.                         at: noteIndex asNumber))]]
  23852.         ifFalse: [request reply: (self showComment: (CommentsTable at: commentKey))]! !
  23853.  
  23854. !Comment class methodsFor: 'URL processing' stamp: 'mjg 11/18/97 10:28'!
  23855. showComment: aComment
  23856.     | fileName |
  23857.     fileName := (ServerAction serverDirectory) , 'ShowComment.html'.
  23858.     ^HTMLformatter evalEmbedded: (FileStream fileNamed: fileName) contentsOfEntireFile with: aComment.
  23859.  
  23860. ! !
  23861.  
  23862. !Comment class methodsFor: 'URL processing' stamp: 'mjg 11/18/97 10:28'!
  23863. showNote: aNote
  23864.     | fileName |
  23865.     fileName := (ServerAction serverDirectory) , 'ShowNote.html'.
  23866.     ^HTMLformatter evalEmbedded: (FileStream fileNamed: fileName) contentsOfEntireFile with: aNote.
  23867. ! !
  23868. ByteArray variableByteSubclass: #CompiledMethod
  23869.     instanceVariableNames: ''
  23870.     classVariableNames: 'LargeFrame SmallFrame SpecialConstants TempNameCache '
  23871.     poolDictionaries: ''
  23872.     category: 'Kernel-Methods'!
  23873. !CompiledMethod commentStamp: 'di 5/22/1998 16:33' prior: 0!
  23874. CompiledMethod comment:
  23875. 'I represent a method suitable for interpretation by the virtual machine. My instances have pointer fields, including a header and some literals, followed by non-pointer fields comprising the byte encoded instructions for the method. The header encodes the number of arguments, the number of literals, and the amount of temporary space needed (for context allocation).
  23876.     
  23877. An extra three bytes are added after the executable code. These contain an external file address to the source code for the method.'!
  23878.  
  23879.  
  23880. !CompiledMethod methodsFor: 'initialize-release'!
  23881. copyWithTrailerBytes: bytes
  23882. "Testing:
  23883.     (CompiledMethod compiledMethodAt: #copyWithTrailerBytes:)
  23884.         tempNamesPut: 'copy end '
  23885. "
  23886.     | copy end start |
  23887.     start _ self initialPC.
  23888.     end _ self endPC.
  23889.     copy _ CompiledMethod newMethod: end - start + 1 + bytes size
  23890.                 header: self header.
  23891.     1 to: self numLiterals do: [:i | copy literalAt: i put: (self literalAt: i)].
  23892.     start to: end do: [:i | copy at: i put: (self at: i)].
  23893.     1 to: bytes size do: [:i | copy at: end + i put: (bytes at: i)].
  23894.     ^ copy! !
  23895.  
  23896. !CompiledMethod methodsFor: 'initialize-release'!
  23897. needsFrameSize: newFrameSize
  23898.     "Set the largeFrameBit to accomodate the newFrameSize.
  23899.     NOTE: I think the >= below is overly cautious.
  23900.     Recompile the system with just > some day - DI 2/26/96"
  23901.     | largeFrameBit header |
  23902.     largeFrameBit _ 16r20000.
  23903.     (self numTemps + newFrameSize) >= LargeFrame
  23904.         ifTrue: [^self error: 'Cannot compile--stack including temps is too deep'].
  23905.     header _ self objectAt: 1.
  23906.     (header bitAnd: largeFrameBit) ~= 0
  23907.         ifTrue: [header _ header - largeFrameBit].
  23908.     self objectAt: 1 put: header
  23909.             + ((self numTemps + newFrameSize) >= SmallFrame
  23910.                     ifTrue: [largeFrameBit]
  23911.                     ifFalse: [0])! !
  23912.  
  23913.  
  23914. !CompiledMethod methodsFor: 'accessing'!
  23915. bePrimitive: primitiveIndex 
  23916.     "Used in conjunction with simulator only"
  23917.     self objectAt: 1
  23918.         put: ((self objectAt: 1) bitAnd: 16rFFFFFE00) + primitiveIndex! !
  23919.  
  23920. !CompiledMethod methodsFor: 'accessing'!
  23921. endPC
  23922.     "Answer the index of the last bytecode."
  23923.     | flagByte |
  23924.     flagByte _ self last.
  23925.     flagByte = 0 ifTrue:
  23926.         ["If last byte = 0, may be either 0, 0, 0, 0 or just 0"
  23927.         1 to: 4 do: [:i | (self at: self size - i) = 0 ifFalse: [^ self size - i]]].
  23928.     flagByte < 252 ifTrue:
  23929.         ["Magic sources (tempnames encoded in last few bytes)"
  23930.         ^ self size - self last - 1].
  23931.     "Normal 4-byte source pointer"
  23932.     ^ self size - 4! !
  23933.  
  23934. !CompiledMethod methodsFor: 'accessing'!
  23935. frameSize
  23936.     "Answer the size of temporary frame needed to run the receiver."
  23937.  
  23938.     (self header noMask: 16r20000)
  23939.         ifTrue: [^ SmallFrame]
  23940.         ifFalse: [^ LargeFrame]! !
  23941.  
  23942. !CompiledMethod methodsFor: 'accessing'!
  23943. initialPC
  23944.     "Answer the program counter for the receiver's first bytecode."
  23945.  
  23946.     ^ (self numLiterals + 1) * 4 + 1! !
  23947.  
  23948. !CompiledMethod methodsFor: 'accessing'!
  23949. numArgs
  23950.     "Answer the number of arguments the receiver takes."
  23951.  
  23952.     ^ (self header bitShift: -24) bitAnd: 16r1F! !
  23953.  
  23954. !CompiledMethod methodsFor: 'accessing'!
  23955. numLiterals
  23956.     "Answer the number of literals used by the receiver."
  23957.     
  23958.     ^ (self header bitShift: -9) bitAnd: 16rFF! !
  23959.  
  23960. !CompiledMethod methodsFor: 'accessing'!
  23961. numTemps
  23962.     "Answer the number of temporary variables used by the receiver."
  23963.     
  23964.     ^ (self header bitShift: -18) bitAnd: 16r3F! !
  23965.  
  23966. !CompiledMethod methodsFor: 'accessing' stamp: 'jm 9/18/97 21:06'!
  23967. primitive
  23968.     "Answer the primitive index associated with the receiver.
  23969.     Zero indicates that this is not a primitive method.
  23970.     We currently allow 11 bits of primitive index, but they are in two places
  23971.     for  backward compatibility.  The time to unpack is negligible,
  23972.     since the reconstituted full index is stored in the method cache."
  23973.     | primBits |
  23974.     primBits _ self header bitAnd: 16r300001FF.
  23975.     primBits > 16r1FF
  23976.         ifTrue: [^ (primBits bitAnd: 16r1FF) + (primBits bitShift: -19)]
  23977.         ifFalse: [^ primBits]! !
  23978.  
  23979. !CompiledMethod methodsFor: 'accessing'!
  23980. returnField
  23981.     "Answer the index of the instance variable returned by a quick return 
  23982.     method."
  23983.     | prim |
  23984.     prim _ self primitive.
  23985.     prim < 264
  23986.         ifTrue: [self error: 'only meaningful for quick-return']
  23987.         ifFalse: [^ prim - 264]! !
  23988.  
  23989. !CompiledMethod methodsFor: 'accessing' stamp: 'sw 8/15/97 16:17'!
  23990. selector
  23991.     "This is slow, so don't call it frivolously"
  23992.     ^ self who last! !
  23993.  
  23994.  
  23995. !CompiledMethod methodsFor: 'comparing'!
  23996. = method
  23997.     "Answer whether the receiver implements the same code as the 
  23998.     argument, method."
  23999.     (method isKindOf: CompiledMethod) ifFalse: [^false].
  24000.     self size = method size ifFalse: [^false].
  24001.     self header = method header ifFalse: [^false].
  24002.     self literals = method literals ifFalse: [^false].
  24003.     self initialPC to: self endPC do:
  24004.         [:i | (self at: i) = (method at: i) ifFalse: [^false]].
  24005.     ^true! !
  24006.  
  24007.  
  24008. !CompiledMethod methodsFor: 'testing'!
  24009. isQuick
  24010.     "Answer whether the receiver is a quick return (of self or of an instance 
  24011.     variable)."
  24012.     ^ self primitive >= 256! !
  24013.  
  24014. !CompiledMethod methodsFor: 'testing'!
  24015. isReturnField
  24016.     "Answer whether the receiver is a quick return of an instance variable."
  24017.     ^ self primitive >= 264! !
  24018.  
  24019. !CompiledMethod methodsFor: 'testing'!
  24020. isReturnSelf
  24021.     "Answer whether the receiver is a quick return of self."
  24022.  
  24023.     ^ self primitive = 256! !
  24024.  
  24025. !CompiledMethod methodsFor: 'testing'!
  24026. isReturnSpecial
  24027.     "Answer whether the receiver is a quick return of self or constant."
  24028.  
  24029.     ^ self primitive between: 256 and: 263! !
  24030.  
  24031.  
  24032. !CompiledMethod methodsFor: 'printing'!
  24033. decompileString
  24034.     | clAndSel cl sel |
  24035.     clAndSel _ self who.
  24036.     cl _ clAndSel first.
  24037.     sel _ clAndSel last.
  24038.     ^ (cl decompilerClass new
  24039.             decompile: sel in: cl method: self) decompileString! !
  24040.  
  24041. !CompiledMethod methodsFor: 'printing'!
  24042. printOn: aStream 
  24043.     "Overrides method inherited from the byte arrayed collection."
  24044.  
  24045.     aStream nextPutAll: 'a CompiledMethod'! !
  24046.  
  24047. !CompiledMethod methodsFor: 'printing'!
  24048. storeLiteralsOn: aStream forClass: aBehavior
  24049.     "Store the literals referenced by the receiver on aStream, each terminated by a space."
  24050.  
  24051.     | literal |
  24052.     2 to: self numLiterals + 1 do:
  24053.         [:index |
  24054.          aBehavior storeLiteral: (self objectAt: index) on: aStream.
  24055.          aStream space]! !
  24056.  
  24057. !CompiledMethod methodsFor: 'printing'!
  24058. storeOn: aStream
  24059.     | noneYet |
  24060.     aStream nextPutAll: '(('.
  24061.     aStream nextPutAll: self class name.
  24062.     aStream nextPutAll: ' newMethod: '.
  24063.     aStream store: self size - self initialPC + 1.
  24064.     aStream nextPutAll: ' header: '.
  24065.     aStream store: self header.
  24066.     aStream nextPut: $).
  24067.     noneYet _ self storeElementsFrom: self initialPC to: self endPC on: aStream.
  24068.     1 to: self numLiterals do:
  24069.         [:index |
  24070.         noneYet
  24071.             ifTrue: [noneYet _ false]
  24072.             ifFalse: [aStream nextPut: $;].
  24073.         aStream nextPutAll: ' literalAt: '.
  24074.         aStream store: index.
  24075.         aStream nextPutAll: ' put: '.
  24076.         aStream store: (self literalAt: index)].
  24077.     noneYet ifFalse: [aStream nextPutAll: '; yourself'].
  24078.     aStream nextPut: $)! !
  24079.  
  24080. !CompiledMethod methodsFor: 'printing'!
  24081. symbolic
  24082.     "Answer a String that contains a list of all the byte codes in a method 
  24083.     with a short description of each." 
  24084.     | aStream |
  24085.     self isQuick ifTrue: 
  24086.         [self isReturnSpecial ifTrue: [^ 'Quick return ' ,
  24087.                 (#('self' 'true' 'false' 'nil' '-1' '0' '1' '2')
  24088.                         at: self primitive - 255)].
  24089.         ^ 'Quick return field ' , self returnField printString , ' (0-based)'].
  24090.     aStream _ WriteStream on: (String new: 1000).
  24091.     self primitive > 0 
  24092.         ifTrue: 
  24093.             [aStream nextPutAll: '<primitive: '.
  24094.             aStream print: self primitive.
  24095.             aStream nextPut: $>.
  24096.             aStream cr].
  24097.     (InstructionPrinter on: self) printInstructionsOn: aStream.
  24098.     ^aStream contents! !
  24099.  
  24100. !CompiledMethod methodsFor: 'printing' stamp: 'jm 9/3/97 11:05'!
  24101. who 
  24102.     "Answer an Array of the class in which the receiver is defined and the 
  24103.     selector to which it corresponds."
  24104.  
  24105.     Smalltalk allBehaviorsDo:
  24106.         [:class |
  24107.         class selectorsDo:
  24108.             [:sel |
  24109.             (class compiledMethodAt: sel) == self 
  24110.                 ifTrue: [^Array with: class with: sel]]].
  24111.     ^ Array with: #unknown with: #unknown
  24112. ! !
  24113.  
  24114.  
  24115. !CompiledMethod methodsFor: 'literals' stamp: 'di 10/17/97 22:38'!
  24116. hasLiteral: literal 
  24117.     "Answer whether the receiver references the argument, literal."
  24118.  
  24119.     <primitive: 132>  "a fast primitive operation equivalent to..."
  24120.  
  24121.     2 to: self numLiterals + 1 do:
  24122.         [:index |
  24123.         literal == (self objectAt: index) ifTrue: [^ true]].
  24124.     ^ false! !
  24125.  
  24126. !CompiledMethod methodsFor: 'literals' stamp: 'di 8/15/97 09:51'!
  24127. hasLiteralSuchThat: litBlock
  24128.     "Answer true if litBlock returns true for any literal in this method, even if imbedded in array structure."
  24129.     | lit |
  24130.     2 to: self numLiterals + 1 do:
  24131.         [:index | lit _ self objectAt: index.
  24132.         (litBlock value: lit) ifTrue: [^ true].
  24133.         (lit class == Array and: [lit hasLiteralSuchThat: litBlock]) ifTrue: [^ true]].
  24134.     ^false! !
  24135.  
  24136. !CompiledMethod methodsFor: 'literals'!
  24137. header
  24138.     "Answer the word containing the information about the form of the 
  24139.     receiver and the form of the context needed to run the receiver."
  24140.  
  24141.     ^self objectAt: 1! !
  24142.  
  24143. !CompiledMethod methodsFor: 'literals'!
  24144. literalAt: index 
  24145.     "Answer the literal indexed by the argument."
  24146.  
  24147.     ^self objectAt: index + 1! !
  24148.  
  24149. !CompiledMethod methodsFor: 'literals'!
  24150. literalAt: index put: value 
  24151.     "Replace the literal indexed by the first argument with the second 
  24152.     argument. Answer the second argument."
  24153.  
  24154.     ^self objectAt: index + 1 put: value! !
  24155.  
  24156. !CompiledMethod methodsFor: 'literals'!
  24157. literals
  24158.     "Answer an Array of the literals referenced by the receiver."
  24159.     | literals numberLiterals |
  24160.     literals _ Array new: (numberLiterals _ self numLiterals).
  24161.     1 to: numberLiterals do:
  24162.         [:index |
  24163.         literals at: index put: (self objectAt: index + 1)].
  24164.     ^literals! !
  24165.  
  24166. !CompiledMethod methodsFor: 'literals'!
  24167. literalStrings
  24168.     | lits litStrs |
  24169.     lits _ self literals.
  24170.     litStrs _ OrderedCollection new: lits size * 3.
  24171.     self literals do:
  24172.         [:lit | 
  24173.         (lit isMemberOf: Association)
  24174.             ifTrue: [litStrs addLast: lit key]
  24175.             ifFalse: [(lit isMemberOf: Symbol)
  24176.                 ifTrue: [litStrs addAll: lit keywords]
  24177.                 ifFalse: [litStrs addLast: lit printString]]].
  24178.     ^ litStrs! !
  24179.  
  24180. !CompiledMethod methodsFor: 'literals'!
  24181. objectAt: index 
  24182.     "Primitive. Answer the method header (if index=1) or a literal (if index 
  24183.     >1) from the receiver. Essential. See Object documentation 
  24184.     whatIsAPrimitive."
  24185.  
  24186.     <primitive: 68>
  24187.     self primitiveFailed! !
  24188.  
  24189. !CompiledMethod methodsFor: 'literals'!
  24190. objectAt: index put: value 
  24191.     "Primitive. Store the value argument into a literal in the receiver. An 
  24192.     index of 2 corresponds to the first literal. Fails if the index is less than 2 
  24193.     or greater than the number of literals. Answer the value as the result. 
  24194.     Normally only the compiler sends this message, because only the 
  24195.     compiler stores values in CompiledMethods. Essential. See Object 
  24196.     documentation whatIsAPrimitive."
  24197.  
  24198.     <primitive: 69>
  24199.     self primitiveFailed! !
  24200.  
  24201.  
  24202. !CompiledMethod methodsFor: 'scanning'!
  24203. messages
  24204.     "Answer a Set of all the message selectors sent by this method."
  24205.  
  24206.     | scanner aSet |
  24207.     aSet _ Set new.
  24208.     scanner _ InstructionStream on: self.
  24209.     scanner    
  24210.         scanFor: 
  24211.             [:x | 
  24212.             scanner addSelectorTo: aSet.
  24213.             false    "keep scanning"].
  24214.     ^aSet! !
  24215.  
  24216. !CompiledMethod methodsFor: 'scanning'!
  24217. readsField: varIndex 
  24218.     "Answer whether the receiver loads the instance variable indexed by the 
  24219.     argument."
  24220.  
  24221.     self isReturnField ifTrue: [^self returnField + 1 = varIndex].
  24222.     varIndex <= 16 ifTrue: [^ self scanFor: varIndex - 1].
  24223.     varIndex <= 64 ifTrue: [^ self scanLongLoad: varIndex - 1].
  24224.     ^ self scanVeryLongLoad: 64 offset: varIndex - 1! !
  24225.  
  24226. !CompiledMethod methodsFor: 'scanning'!
  24227. readsRef: literalAssociation 
  24228.     "Answer whether the receiver loads the argument."
  24229.     | lit |
  24230.     lit _ self literals indexOf: literalAssociation ifAbsent: [^false].
  24231.     lit <= 32 ifTrue: [^self scanFor: 64 + lit - 1].
  24232.     lit <= 64 ifTrue: [^self scanLongLoad: 192 + lit - 1].
  24233.     ^ self scanVeryLongLoad: 128 offset: lit - 1! !
  24234.  
  24235. !CompiledMethod methodsFor: 'scanning'!
  24236. scanFor: byte 
  24237.     "Answer whether the receiver contains the argument as a bytecode."
  24238.  
  24239.     ^ (InstructionStream on: self) scanFor: [:instr | instr = byte]
  24240. "
  24241. Smalltalk browseAllSelect: [:m | m scanFor: 134]
  24242. "! !
  24243.  
  24244. !CompiledMethod methodsFor: 'scanning'!
  24245. scanLongLoad: extension 
  24246.     "Answer whether the receiver contains a long load whose extension is the 
  24247.     argument."
  24248.  
  24249.     | scanner |
  24250.     scanner _ InstructionStream on: self.
  24251.     ^scanner scanFor: [:instr | instr = 128 and: [scanner followingByte = extension]]! !
  24252.  
  24253. !CompiledMethod methodsFor: 'scanning'!
  24254. scanLongStore: extension 
  24255.     "Answer whether the receiver contains a long store whose extension is 
  24256.     the argument."
  24257.     | scanner |
  24258.     scanner _ InstructionStream on: self.
  24259.     ^scanner scanFor: 
  24260.         [:instr |  (instr = 129 or: [instr = 130]) and: [scanner followingByte = extension]]! !
  24261.  
  24262. !CompiledMethod methodsFor: 'scanning'!
  24263. scanVeryLongLoad: extension offset: offset
  24264.     "Answer whether the receiver contains a long load whose extension is the 
  24265.     argument."
  24266.     | scanner |
  24267.     scanner _ InstructionStream on: self.
  24268.     ^ scanner scanFor: [:instr | (instr = 132 and: [scanner followingByte = extension])
  24269.                                             and: [scanner thirdByte = offset]]! !
  24270.  
  24271. !CompiledMethod methodsFor: 'scanning' stamp: 'di 6/25/97 19:08'!
  24272. scanVeryLongStore: extension offset: offset
  24273.     "Answer whether the receiver contains a long load with the given offset.
  24274.     Note that the constant +32 is the known difference between a
  24275.     store and a storePop for instVars, and it will always fail on literal variables,
  24276.     but these only use store (followed by pop) anyway."
  24277.     | scanner ext |
  24278.     scanner _ InstructionStream on: self.
  24279.     ^ scanner scanFor:
  24280.         [:instr | (instr = 132 and: [(ext _ scanner followingByte) = extension
  24281.                                             or: ["might be a store/pop into rcvr"
  24282.                                                 ext = (extension+32)]])
  24283.                             and: [scanner thirdByte = offset]]! !
  24284.  
  24285. !CompiledMethod methodsFor: 'scanning'!
  24286. sendsToSuper
  24287.     "Answer whether the receiver sends any message to super."
  24288.     | scanner |
  24289.     scanner _ InstructionStream on: self.
  24290.     ^ scanner scanFor: 
  24291.         [:instr |  instr = 16r85 or: [instr = 16r84
  24292.                         and: [scanner followingByte between: 16r20 and: 16r3F]]]! !
  24293.  
  24294. !CompiledMethod methodsFor: 'scanning'!
  24295. writesField: field 
  24296.     "Answer whether the receiver stores into the instance variable indexed 
  24297.     by the argument."
  24298.  
  24299.     self isQuick ifTrue: [^false].
  24300.     field <= 8 ifTrue: [^ (self scanFor: 96 + field - 1)
  24301.                         or: [self scanLongStore: field - 1]].
  24302.     field <= 64 ifTrue: [^ self scanLongStore: field - 1].
  24303.     ^ self scanVeryLongStore: 160 offset: field - 1! !
  24304.  
  24305. !CompiledMethod methodsFor: 'scanning'!
  24306. writesRef: ref 
  24307.     "Answer whether the receiver stores the argument."
  24308.     | lit |
  24309.     lit _ self literals indexOf: ref ifAbsent: [^false].
  24310.     lit <= 64 ifTrue: [^ self scanLongStore: 192 + lit - 1].
  24311.     ^ self scanVeryLongStore: 224 offset: lit - 1! !
  24312.  
  24313.  
  24314. !CompiledMethod methodsFor: 'source code management'!
  24315. cacheTempNames: names
  24316.  
  24317.     TempNameCache _ Association key: self value: names! !
  24318.  
  24319. !CompiledMethod methodsFor: 'source code management'!
  24320. copyWithTempNames: tempNames
  24321.     | tempStr |
  24322.     tempStr _ String streamContents:
  24323.         [:strm | tempNames do: [:n | strm nextPutAll: n; space]].
  24324.     ^ self copyWithTrailerBytes: (self qCompress: tempStr)! !
  24325.  
  24326. !CompiledMethod methodsFor: 'source code management'!
  24327. fileIndex
  24328.     "Answer the index of the sources file on which this method is stored, as follows:
  24329.         1:    .sources file
  24330.         2:    .changes file
  24331.         3 and 4 are also available for future extension of source code management"
  24332.  
  24333.     self last < 252 ifTrue: [^ 0  "no source"].
  24334.     ^ self last - 251
  24335.  
  24336.     ! !
  24337.  
  24338. !CompiledMethod methodsFor: 'source code management'!
  24339. filePosition
  24340.     "Answer the file position of this method's source code."
  24341.     | pos |
  24342.     self last < 252 ifTrue: [^ 0  "no source"].
  24343.     pos _ 0.
  24344.     self size - 1 to: self size - 3 by: -1 do: [:i | pos _ pos * 256 + (self at: i)].
  24345.     ^ pos! !
  24346.  
  24347. !CompiledMethod methodsFor: 'source code management' stamp: 'di 8/15/97 14:27'!
  24348. getSourceFor: selector in: class
  24349.     "Retrieve or reconstruct the source code for this method."
  24350.     | source flagByte |
  24351.     flagByte _ self last.
  24352.     flagByte = 0 ifTrue:
  24353.         ["No source pointer -- decompile without temp names"
  24354.         ^ (class decompilerClass new decompile: selector in: class method: self)
  24355.             decompileString].
  24356.     flagByte < 252 ifTrue:
  24357.         ["Magic sources -- decompile with temp names"
  24358.         ^ ((class decompilerClass new withTempNames: self tempNames)
  24359.                 decompile: selector in: class method: self)
  24360.             decompileString].
  24361.  
  24362.     "Situation normal;  read the sourceCode from the file"
  24363.     (source _ self getSourceFromFile) == nil ifFalse: [^ source].
  24364.  
  24365.     "Something really wrong -- decompile blind (no temps)"
  24366.     ^ (class decompilerClass new decompile: selector in: class method: self)
  24367.             decompileString! !
  24368.  
  24369. !CompiledMethod methodsFor: 'source code management' stamp: 'tk 12/12/97 13:03'!
  24370. getSourceFromFile
  24371.     "Read the source code from file, determining source file index and
  24372.     file position from the last 3 bytes of this method."
  24373.     | position |
  24374.     (position _ self filePosition) = 0 ifTrue: [^ nil].
  24375.     ^ (RemoteString newFileNumber: self fileIndex position: position)
  24376.             text! !
  24377.  
  24378. !CompiledMethod methodsFor: 'source code management'!
  24379. putSource: sourceStr fromParseNode: methodNode class: class category: catName
  24380.     inFile: fileIndex priorMethod: priorMethod
  24381.  
  24382.     ^ self putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble:
  24383.             [:file | class printCategoryChunk: catName on: file priorMethod: priorMethod.
  24384.             file cr]! !
  24385.  
  24386. !CompiledMethod methodsFor: 'source code management' stamp: '6/5/97 di'!
  24387. putSource: sourceStr fromParseNode: methodNode class: class category: catName
  24388.     withStamp: changeStamp inFile: fileIndex priorMethod: priorMethod
  24389.  
  24390.     ^ self putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble:
  24391.             [:file |
  24392.             class printCategoryChunk: catName on: file
  24393.                 withStamp: changeStamp priorMethod: priorMethod.
  24394.             file cr]! !
  24395.  
  24396. !CompiledMethod methodsFor: 'source code management' stamp: 'tk 12/11/97 16:21'!
  24397. putSource: sourceStr fromParseNode: methodNode inFile: fileIndex withPreamble: preambleBlock
  24398.     "Store the source code for the receiver on an external file.
  24399.     If no sources are available, i.e., SourceFile is nil, then store
  24400.     temp names for decompilation at the end of the method.
  24401.     If the fileIndex is 1, print on *.sources;  if it is 2, print on *.changes,
  24402.     in each case, storing a 4-byte source code pointer at the method end."
  24403.     | file remoteString |
  24404.     (SourceFiles == nil or: [(file _ SourceFiles at: fileIndex) == nil]) ifTrue:
  24405.         [^ self become: (self copyWithTempNames: methodNode tempNames)].
  24406.     file setToEnd.
  24407.     preambleBlock value: file.  "Write the preamble"
  24408.     remoteString _ RemoteString newString: sourceStr
  24409.                         onFileNumber: fileIndex toFile: file.
  24410.     file nextChunkPut: ' '; flush.
  24411.     self setSourcePosition: remoteString position inFile: fileIndex! !
  24412.  
  24413. !CompiledMethod methodsFor: 'source code management'!
  24414. qCompress: str
  24415.     "A very simple text compression routine designed for method temp names.
  24416.     Most common 12 chars get values 0-11 packed in one 4-bit nibble;
  24417.     others get values 12-15 (2 bits) * 16 plus next nibble.
  24418.     Last char of str must be a space so it may be dropped without
  24419.     consequence if output ends on odd nibble."
  24420.     | charTable odd ix oddNibble |
  24421.     charTable _  "Character encoding table must match qDecompress:"
  24422.     ' eatrnoislcm bdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.
  24423.     ^ ByteArray streamContents:
  24424.         [:strm | odd _ true.  "Flag for odd or even nibble out"
  24425.         str do:
  24426.             [:char | ix _ (charTable indexOf: char) - 1.
  24427.             (ix <= 12 ifTrue: [ix]
  24428.                 ifFalse: [Array with: ix//16+12 with: ix\\16])
  24429.                 do:
  24430.                 [:nibble | (odd _ odd not)
  24431.                     ifTrue: [strm nextPut: oddNibble*16 + nibble]
  24432.                     ifFalse: [oddNibble _ nibble]]].
  24433.         strm nextPut: strm position]
  24434. "
  24435.   | m s |  m _ CompiledMethod new.
  24436. s _ 'charTable odd ix oddNibble '.
  24437. ^ Array with: s size with: (m qCompress: s) size
  24438.     with: (m qDecompress: (m qCompress: s))
  24439. "
  24440. ! !
  24441.  
  24442. !CompiledMethod methodsFor: 'source code management'!
  24443. qDecompress: byteArray
  24444.     "Decompress strings compressed by qCompress:.
  24445.     Most common 12 chars get values 0-11 packed in one 4-bit nibble;
  24446.     others get values 12-15 (2 bits) * 16 plus next nibble"
  24447.     |  charTable extended ext |
  24448.     charTable _  "Character encoding table must match qCompress:"
  24449.     ' eatrnoislcm bdfghjkpquvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.
  24450.     ^ String streamContents:
  24451.         [:strm | extended _ false.  "Flag for 2-nibble characters"
  24452.         byteArray do:
  24453.             [:byte | 
  24454.             (Array with: byte//16 with: byte\\16)
  24455.                 do:
  24456.                 [:nibble | extended
  24457.                     ifTrue: [strm nextPut: (charTable at: ext*16+nibble + 1). extended _ false]
  24458.                     ifFalse: [nibble < 12 ifTrue: [strm nextPut: (charTable at: nibble + 1)]
  24459.                                     ifFalse: [ext _ nibble-12.  extended _ true]]]]]! !
  24460.  
  24461. !CompiledMethod methodsFor: 'source code management' stamp: 'di 6/15/97 09:14'!
  24462. setSourcePointer: srcPointer
  24463.     self setSourcePosition: srcPointer \\ 16r1000000 inFile: srcPointer // 16r1000000! !
  24464.  
  24465. !CompiledMethod methodsFor: 'source code management'!
  24466. setSourcePosition: position inFile: fileIndex 
  24467.     "Store the location of the source code for the receiver in the receiver. The 
  24468.     location consists of which source file (*.sources or *.changes) and the 
  24469.     position in that file."
  24470.  
  24471.     fileIndex > 4 ifTrue: [^ self error: 'invalid file number'].
  24472.     self at: self size put: 251 + fileIndex.
  24473.     1 to: 3 do: 
  24474.         [:i | self at: self size - i put: ((position bitShift: (i-3)*8) bitAnd: 16rFF)].
  24475. ! !
  24476.  
  24477. !CompiledMethod methodsFor: 'source code management'!
  24478. setTempNamesIfCached: aBlock
  24479.     "This is a cache used by the debugger, independent of the storage of
  24480.     temp names when the system is converted to decompilation with temps."
  24481.     TempNameCache == nil ifTrue: [^self].
  24482.     TempNameCache key == self
  24483.         ifTrue: [aBlock value: TempNameCache value]! !
  24484.  
  24485. !CompiledMethod methodsFor: 'source code management' stamp: 'di 6/15/97 09:13'!
  24486. sourcePointer
  24487.     ^ (self fileIndex * 16r1000000) + self filePosition! !
  24488.  
  24489. !CompiledMethod methodsFor: 'source code management'!
  24490. tempNames
  24491.     | byteCount bytes |
  24492.     byteCount _ self at: self size.
  24493.     byteCount = 0 ifTrue: [^ Array new].
  24494.     bytes _ (ByteArray new: byteCount)
  24495.         replaceFrom: 1 to: byteCount with: self 
  24496.         startingAt: self size - byteCount.
  24497.     ^ (self qDecompress: bytes) findTokens: ' '! !
  24498.  
  24499.  
  24500. !CompiledMethod methodsFor: 'file in/out' stamp: 'tk 3/24/98 12:58'!
  24501. readDataFrom: aDataStream size: varsOnDisk
  24502.     "Make self be an object based on the contents of aDataStream, which was generated by the object's storeDataOn: method. Return self.  Must read both objects for the literals and bytes for the bytecodes."
  24503.  
  24504.     | lits |
  24505.     aDataStream beginReference: self.
  24506.     self objectAt: 1 put: aDataStream next.    "the header"
  24507.     lits _ self numLiterals + 1.    "counting header"
  24508.     2 to: lits do:
  24509.         [:ii | self objectAt: ii put: aDataStream next].
  24510.     lits*4+1 to: self basicSize do:
  24511.         [:ii | self basicAt: ii put: aDataStream byteStream next].
  24512.             "Get raw bytes directly from the file"
  24513.     ^ self! !
  24514.  
  24515. !CompiledMethod methodsFor: 'file in/out' stamp: 'tk 3/26/98 09:10'!
  24516. storeDataOn: aDataStream
  24517.     "Store myself on a DataStream.  I am a mixture of objects and raw data bytes.  Only use this for blocks.  Normal methodDictionaries should not be put out using ReferenceStreams.  Their fileOut should be attached to the beginning of the file."
  24518.  
  24519.     | byteLength lits |
  24520.     "No inst vars of the normal type"
  24521.     byteLength _ self basicSize.
  24522.     aDataStream
  24523.         beginInstance: self class
  24524.         size: byteLength.
  24525.     lits _ self numLiterals + 1.    "counting header"
  24526.     1 to: lits do:
  24527.         [:ii | aDataStream nextPut: (self objectAt: ii)].
  24528.     lits*4+1 to: byteLength do:
  24529.         [:ii | aDataStream byteStream nextPut: (self basicAt: ii)].
  24530.             "write bytes straight through to the file"! !
  24531.  
  24532. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  24533.  
  24534. CompiledMethod class
  24535.     instanceVariableNames: ''!
  24536.  
  24537. !CompiledMethod class methodsFor: 'class initialization'!
  24538. initialize    "CompiledMethod initialize"
  24539.     "Initialize class variables specifying the size of the temporary frame
  24540.     needed to run instances of me."
  24541.  
  24542.     SmallFrame _ 12.    "Context range for temps+stack"
  24543.     LargeFrame _ 32.! !
  24544.  
  24545.  
  24546. !CompiledMethod class methodsFor: 'instance creation'!
  24547. new
  24548.     "This will not make a meaningful method, but it could be used
  24549.     to invoke some otherwise useful method in this class."
  24550.     ^ self newMethod: 0 header: 0! !
  24551.  
  24552. !CompiledMethod class methodsFor: 'instance creation' stamp: 'jm 9/18/97 21:06'!
  24553. newBytes: numberOfBytes nArgs: nArgs nTemps: nTemps nStack: stackSize nLits: nLits primitive: primitiveIndex
  24554.     "Answer an instance of me. The header is specified by the message 
  24555.     arguments. The remaining parts are not as yet determined."
  24556.     | largeBit primBits |
  24557.     largeBit _ (nTemps + stackSize) > SmallFrame ifTrue: [1] ifFalse: [0].
  24558.     primBits _ primitiveIndex <= 16r1FF
  24559.         ifTrue: [primitiveIndex]
  24560.         ifFalse: ["For now the high 2 bits of primitive no. are in high bits of header"
  24561.                 (primitiveIndex bitAnd: 16r1FF) + ((primitiveIndex bitAnd: 16r600) bitShift: 19)].
  24562.     ^ self newMethod: numberOfBytes + 4     " +4 to store source code ptr" 
  24563.         header: (nArgs bitShift: 24) +
  24564.                 (nTemps bitShift: 18) +
  24565.                 (largeBit bitShift: 17) +
  24566.                 (nLits bitShift: 9) +
  24567.                 primBits! !
  24568.  
  24569. !CompiledMethod class methodsFor: 'instance creation'!
  24570. newMethod: numberOfBytes header: headerWord 
  24571.     "Primitive. Answer an instance of me. The number of literals (and other 
  24572.     information) is specified the headerWord. The first argument specifies 
  24573.     the number of fields for bytecodes in the method. Fail if either 
  24574.     argument is not a SmallInteger, or if numberOfBytes is negative. Once 
  24575.     the header of a method is set by this primitive, it cannot be changed in 
  24576.     any way. Essential. See Object documentation whatIsAPrimitive."
  24577.  
  24578.     <primitive: 79>
  24579.     (numberOfBytes isInteger and:
  24580.      [headerWord isInteger and:
  24581.      [numberOfBytes >= 0]]) ifTrue: [
  24582.         "args okay; space must be low"
  24583.         Smalltalk signalLowSpace.
  24584.         "retry if user proceeds"
  24585.         ^ self newMethod: numberOfBytes header: headerWord
  24586.     ].
  24587.     ^self primitiveFailed! !
  24588.  
  24589. !CompiledMethod class methodsFor: 'instance creation'!
  24590. toReturnConst: constCode
  24591.     "Answer an instance of me that is a quick return of a constant
  24592.     constCode = 1...7  ->  true, false, nil, -1, 0, 1, 2."
  24593.  
  24594.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256 + constCode! !
  24595.  
  24596. !CompiledMethod class methodsFor: 'instance creation'!
  24597. toReturnConstant: index 
  24598.     "Answer an instance of me that is a quick return of the constant
  24599.     indexed in (true false nil -1 0 1 2)."
  24600.  
  24601.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256 + index
  24602. ! !
  24603.  
  24604. !CompiledMethod class methodsFor: 'instance creation'!
  24605. toReturnField: field 
  24606.     "Answer an instance of me that is a quick return of the instance variable 
  24607.     indexed by the argument, field."
  24608.  
  24609.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 264 + field
  24610. ! !
  24611.  
  24612. !CompiledMethod class methodsFor: 'instance creation'!
  24613. toReturnSelf
  24614.     "Answer an instance of me that is a quick return of the instance (^self)."
  24615.  
  24616.     ^ self newBytes: 0 nArgs: 0 nTemps: 0 nStack: 0 nLits: 0 primitive: 256
  24617. ! !
  24618. Object subclass: #Compiler
  24619.     instanceVariableNames: 'sourceStream requestor class context '
  24620.     classVariableNames: ''
  24621.     poolDictionaries: ''
  24622.     category: 'System-Compiler'!
  24623. !Compiler commentStamp: 'di 5/22/1998 16:33' prior: 0!
  24624. Compiler comment:
  24625. 'The compiler accepts Smalltalk source code and compiles it with respect to a given class. The user of the compiler supplies a context so that temporary variables are accessible during compilation. If there is an error, a requestor (usually a kind of StringHolderController) is sent the message notify:at:in: so that the error message can be displayed. If there is no error, then the result of compilation is a MethodNode, which is the root of a parse tree whose nodes are kinds of ParseNodes. The parse tree can be sent messages to (1) generate code for a CompiledMethod (this is done for compiling methods or evaluating expressions); (2) pretty-print the code (for formatting); or (3) produce a map from object code back to source code (used by debugger program-counter selection). See also Parser, Encoder, ParseNode.'!
  24626.  
  24627.  
  24628. !Compiler methodsFor: 'error handling'!
  24629. interactive 
  24630.     "Answer whether there is a requestor of the compiler who should be 
  24631.     informed that an error occurred."
  24632.  
  24633.     ^ (requestor == nil or: [requestor isKindOf: SyntaxError]) not! !
  24634.  
  24635. !Compiler methodsFor: 'error handling'!
  24636. notify: aString 
  24637.     "Refer to the comment in Object|notify:."
  24638.  
  24639.     ^self notify: aString at: sourceStream position + 1! !
  24640.  
  24641. !Compiler methodsFor: 'error handling'!
  24642. notify: aString at: location
  24643.     "Refer to the comment in Object|notify:."
  24644.  
  24645.     requestor == nil
  24646.         ifTrue: [^SyntaxError 
  24647.                     errorInClass: class
  24648.                     withCode: 
  24649.                         (sourceStream contents
  24650.                             copyReplaceFrom: location
  24651.                             to: location - 1
  24652.                             with: aString)]
  24653.         ifFalse: [^requestor
  24654.                     notify: aString
  24655.                     at: location
  24656.                     in: sourceStream]! !
  24657.  
  24658.  
  24659. !Compiler methodsFor: 'public access'!
  24660. compile: textOrStream in: aClass notifying: aRequestor ifFail: failBlock 
  24661.     "Answer a MethodNode for the argument, textOrStream. If the 
  24662.     MethodNode can not be created, notify the argument, aRequestor; if 
  24663.     aRequestor is nil, evaluate failBlock instead. The MethodNode is the root 
  24664.     of a parse tree. It can be told to generate a CompiledMethod to be 
  24665.     installed in the method dictionary of the argument, aClass."
  24666.  
  24667.     self from: textOrStream
  24668.         class: aClass
  24669.         context: nil
  24670.         notifying: aRequestor.
  24671.     ^self
  24672.         translate: sourceStream
  24673.         noPattern: false
  24674.         ifFail: failBlock! !
  24675.  
  24676. !Compiler methodsFor: 'public access'!
  24677. evaluate: textOrStream in: aContext to: receiver notifying: aRequestor ifFail: failBlock
  24678.     "Compiles the sourceStream into a parse tree, then generates code into a 
  24679.     method. This method is then installed in the receiver's class so that it 
  24680.     can be invoked. In other words, if receiver is not nil, then the text can 
  24681.     refer to instance variables of that receiver (the Inspector uses this). If 
  24682.     aContext is not nil, the text can refer to temporaries in that context (the 
  24683.     Debugger uses this). If aRequestor is not nil, then it will receive a 
  24684.     notify:at: message before the attempt to evaluate is aborted. Finally, the 
  24685.     compiled method is invoked from here as DoIt or (in the case of 
  24686.     evaluation in aContext) DoItIn:. The method is subsequently removed 
  24687.     from the class, but this will not get done if the invocation causes an 
  24688.     error which is terminated. Such garbage can be removed by executing: 
  24689.     Smalltalk allBehaviorsDo: [:cl | cl removeSelector: #DoIt; removeSelector: 
  24690.     #DoItIn:]."
  24691.  
  24692.     | methodNode method value |
  24693.     class _ (aContext == nil ifTrue: [receiver] ifFalse: [aContext receiver]) class.
  24694.     self from: textOrStream class: class context: aContext notifying: aRequestor.
  24695.     methodNode _ self translate: sourceStream noPattern: true ifFail:
  24696.         [^failBlock value].
  24697.     method _ methodNode generate: #(0 0 0 0).
  24698.     context == nil
  24699.         ifTrue: [class addSelector: #DoIt withMethod: method.
  24700.                 value _ receiver DoIt.
  24701.                 class removeSelectorSimply: #DoIt.
  24702.                 ^value]
  24703.         ifFalse: [class addSelector: #DoItIn: withMethod: method.
  24704.                 value _ receiver DoItIn: context.
  24705.                 class removeSelectorSimply: #DoItIn:.
  24706.                 ^value]! !
  24707.  
  24708. !Compiler methodsFor: 'public access'!
  24709. format: textOrStream in: aClass notifying: aRequestor
  24710.     "Compile a parse tree from the argument, textOrStream. Answer a string 
  24711.     containing the original code, formatted nicely.
  24712.     If the leftShift key is pressed, then decorate the resulting text with
  24713.     color and hypertext actions"
  24714.     | aNode |
  24715.     self from: textOrStream
  24716.         class: aClass
  24717.         context: nil
  24718.         notifying: aRequestor.
  24719.     aNode _ self format: sourceStream noPattern: false ifFail: [^nil].
  24720.     Sensor leftShiftDown
  24721.         ifTrue: [^ aNode decompileText]
  24722.         ifFalse: [^ aNode decompileString]! !
  24723.  
  24724. !Compiler methodsFor: 'public access'!
  24725. parse: textOrStream in: aClass notifying: req
  24726.     "Compile the argument, textOrStream, with respect to the class, aClass, 
  24727.     and answer the MethodNode that is the root of the resulting parse tree. 
  24728.     Notify the argument, req, if an error occurs. The failBlock is defaulted to 
  24729.     an empty block."
  24730.  
  24731.     self from: textOrStream class: aClass context: nil notifying: req.
  24732.     ^self translate: sourceStream noPattern: false ifFail: []! !
  24733.  
  24734.  
  24735. !Compiler methodsFor: 'private'!
  24736. format: aStream noPattern: noPattern ifFail: failBlock
  24737.  
  24738.     | tree |
  24739.     tree _ 
  24740.         Parser new
  24741.             parse: aStream
  24742.             class: class
  24743.             noPattern: noPattern
  24744.             context: context
  24745.             notifying: requestor
  24746.             ifFail: [^failBlock value].
  24747.     ^tree! !
  24748.  
  24749. !Compiler methodsFor: 'private'!
  24750. from: textOrStream class: aClass context: aContext notifying: req
  24751.  
  24752.     (textOrStream isKindOf: PositionableStream)
  24753.         ifTrue: [sourceStream _ textOrStream]
  24754.         ifFalse: [sourceStream _ ReadStream on: textOrStream asString].
  24755.     class _ aClass.
  24756.     context _ aContext.
  24757.     requestor _ req! !
  24758.  
  24759. !Compiler methodsFor: 'private'!
  24760. translate: aStream noPattern: noPattern ifFail: failBlock
  24761.  
  24762.     | tree |
  24763.     tree _ 
  24764.         Parser new
  24765.             parse: aStream
  24766.             class: class
  24767.             noPattern: noPattern
  24768.             context: context
  24769.             notifying: requestor
  24770.             ifFail: [^failBlock value].
  24771.     ^tree! !
  24772.  
  24773. !Compiler methodsFor: 'private'!
  24774. translate: aStream withLocals: localDict noPattern: noPattern ifFail: failBlock
  24775.  
  24776.     | tree |
  24777.     tree _ 
  24778.         Parser new
  24779.             parse: aStream
  24780.             class: class
  24781.             noPattern: noPattern
  24782.             locals: localDict
  24783.             notifying: requestor
  24784.             ifFail: [^failBlock value].
  24785.     ^tree! !
  24786.  
  24787. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  24788.  
  24789. Compiler class
  24790.     instanceVariableNames: ''!
  24791.  
  24792. !Compiler class methodsFor: 'accessing'!
  24793. parserClass
  24794.     "Return a parser class to use for parsing method headers."
  24795.  
  24796.     ^Parser! !
  24797.  
  24798.  
  24799. !Compiler class methodsFor: 'evaluating'!
  24800. evaluate: textOrString 
  24801.     "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, 
  24802.     a Syntax Error view is created rather than notifying any requestor. 
  24803.     Compilation is carried out with respect to nil, i.e., no object, and the 
  24804.     invocation is not logged."
  24805.  
  24806.     ^self evaluate: textOrString for: nil logged: false! !
  24807.  
  24808. !Compiler class methodsFor: 'evaluating'!
  24809. evaluate: textOrString for: anObject logged: logFlag 
  24810.     "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, 
  24811.     a Syntax Error view is created rather than notifying any requestor."
  24812.  
  24813.     ^self evaluate: textOrString for: anObject notifying: nil logged: logFlag! !
  24814.  
  24815. !Compiler class methodsFor: 'evaluating'!
  24816. evaluate: textOrString for: anObject notifying: aController logged: logFlag
  24817.     "Compile and execute the argument, textOrString with respect to the class 
  24818.     of anObject. If a compilation error occurs, notify aController. If both 
  24819.     compilation and execution are successful then, if logFlag is true, log 
  24820.     (write) the text onto a system changes file so that it can be replayed if 
  24821.     necessary."
  24822.  
  24823.     | val |
  24824.     val _ self new
  24825.                 evaluate: textOrString
  24826.                 in: nil
  24827.                 to: anObject
  24828.                 notifying: aController
  24829.                 ifFail: [^nil].
  24830.     logFlag ifTrue: [Smalltalk logChange: textOrString].
  24831.     ^val! !
  24832.  
  24833. !Compiler class methodsFor: 'evaluating'!
  24834. evaluate: textOrString logged: logFlag 
  24835.     "See Compiler|evaluate:for:notifying:logged:. If a compilation error occurs, 
  24836.     a Syntax Error view is created rather than notifying any requestor. 
  24837.     Compilation is carried out with respect to nil, i.e., no object."
  24838.  
  24839.     ^self evaluate: textOrString for: nil logged: logFlag! !
  24840.  
  24841. !Compiler class methodsFor: 'evaluating'!
  24842. evaluate: textOrString notifying: aController logged: logFlag 
  24843.     "See Compiler|evaluate:for:notifying:logged:. Compilation is carried out 
  24844.     with respect to nil, i.e., no object."
  24845.  
  24846.     ^self evaluate: textOrString for: nil notifying: aController logged: logFlag! !
  24847. Player subclass: #Component
  24848.     instanceVariableNames: 'model pinSpecs '
  24849.     classVariableNames: ''
  24850.     poolDictionaries: ''
  24851.     category: 'Morphic-Components'!
  24852.  
  24853. !Component methodsFor: 'initialize' stamp: 'di 5/3/1998 20:23'!
  24854. initComponentIn: aLayout
  24855.     model _ aLayout model.
  24856.     self nameMeIn: aLayout world.
  24857.     self color: Color lightCyan.
  24858.     self showPins.
  24859.     model addDependent: self! !
  24860.  
  24861.  
  24862. !Component methodsFor: 'naming' stamp: 'di 5/3/1998 19:48'!
  24863. chooseNameLike: someName 
  24864.     | stem otherNames i partName |
  24865.     stem _ someName.
  24866.     (stem size > 5 and: [stem endsWith: 'Morph'])
  24867.         ifTrue: [stem _ stem copyFrom: 1 to: stem size - 5].
  24868.     stem _ stem first asLowercase asString , stem allButFirst.
  24869.     otherNames _ self class allInstVarNames asSet.
  24870.     "otherNames addAll: self world allKnownNames."
  24871.     i _ 1.
  24872.     [otherNames includes: (partName _ stem , i printString)]
  24873.         whileTrue: [i _ i + 1].
  24874.     partName _ FillInTheBlank request: 'Please give this part a name'
  24875.                         initialAnswer: partName.
  24876.     partName isEmpty ifTrue: [^ nil].
  24877.     (otherNames includes: partName) ifTrue:
  24878.             [self inform: 'Sorry, that name is already used'.
  24879.             ^ nil].
  24880.     ^ partName! !
  24881.  
  24882. !Component methodsFor: 'naming' stamp: 'di 5/3/1998 19:58'!
  24883. externalName 
  24884.     ^ self class name! !
  24885.  
  24886. !Component methodsFor: 'naming' stamp: 'di 5/3/1998 19:50'!
  24887. nameMeIn: aWorld
  24888.     | stem otherNames i partName className |
  24889.     className _ self class name.
  24890.     stem _ className.
  24891.     (stem size > 5 and: [stem endsWith: 'Morph'])
  24892.         ifTrue: [stem _ stem copyFrom: 1 to: stem size - 5].
  24893.     stem _ stem first asLowercase asString , stem allButFirst.
  24894.     otherNames _ Set newFrom: aWorld allKnownNames.
  24895.     i _ 1.
  24896.     [otherNames includes: (partName _ stem , i printString)]
  24897.         whileTrue: [i _ i + 1].
  24898.     self setNamePropertyTo: partName! !
  24899.  
  24900. !Component methodsFor: 'naming' stamp: 'di 5/3/1998 19:51'!
  24901. renameMe
  24902.     | newName |
  24903.     newName _ self chooseNameLike: self knownName.
  24904.     newName ifNil: [^ nil].
  24905.     self setNamePropertyTo: newName! !
  24906.  
  24907.  
  24908. !Component methodsFor: 'drag and drop' stamp: 'di 5/3/1998 20:08'!
  24909. justDroppedInto: aMorph event: anEvent
  24910.     | theModel |
  24911.     theModel _ aMorph model.
  24912.     ((aMorph isKindOf: ComponentLayout) 
  24913.         and: [theModel isKindOf: Component]) ifFalse:
  24914.         ["Disconnect prior to removal by move"
  24915.         (theModel isKindOf: Component) ifTrue: [self unwire.  model _ nil].
  24916.         ^ self].
  24917.     theModel == model ifTrue: [^ self  "Presumably just a move"].
  24918.     self initComponentIn: aMorph! !
  24919.  
  24920.  
  24921. !Component methodsFor: 'variables' stamp: 'di 5/3/1998 19:46'!
  24922. addVariableNamed: varName
  24923.     | otherNames i partName |
  24924.     "Adjust name if necessary and add it"
  24925.     otherNames _ self class allInstVarNames.
  24926.     i _ nil.
  24927.     [i == nil ifTrue: [partName _ varName] ifFalse: [partName _ varName, i printString].
  24928.     otherNames includes: partName]
  24929.         whileTrue: [i == nil ifTrue: [i _ 1] ifFalse: [i _ i + 1]].
  24930.     self class addInstVarName: partName.
  24931.  
  24932.     "Now compile read method and write-with-change method"
  24933.     self class compile: (String streamContents:
  24934.             [:s | s nextPutAll: partName; cr;
  24935.             tab; nextPutAll: '^', partName])
  24936.         classified: 'view access'
  24937.         notifying: nil.
  24938.     self class compile: (String streamContents:
  24939.             [:s | s nextPutAll: partName, 'Set: newValue'; cr;
  24940.                 tab; nextPutAll: partName, ' _ newValue.'; cr;
  24941.                 tab; nextPutAll: 'self changed: #', partName])
  24942.         classified: 'view access'
  24943.         notifying: nil.
  24944.  
  24945.     ^ Array with: partName asSymbol with: (partName , 'Set:') asSymbol! !
  24946.  
  24947. !Component methodsFor: 'variables' stamp: 'di 5/3/1998 19:58'!
  24948. removeVariableNamed: varName 
  24949.     self class removeSelector: varName.
  24950.     self class removeSelector: (varName , 'Set:') asSymbol.
  24951.     self class removeInstVarName: varName asString! !
  24952.  
  24953.  
  24954. !Component methodsFor: 'misc' stamp: 'di 5/3/1998 20:01'!
  24955. addAddHandMenuItemsForHalo: aMenu hand: aHandMorph
  24956.  
  24957.     super addAddHandMenuItemsForHalo: aMenu hand: aHandMorph.
  24958.     aMenu add: 'delete' action: #dismissMorph! !
  24959.  
  24960. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  24961.  
  24962. Component class
  24963.     instanceVariableNames: ''!
  24964.  
  24965. !Component class methodsFor: 'all' stamp: 'di 4/17/1998 14:02'!
  24966. acceptsLoggingOfCompilation
  24967.     "Log everything for now"
  24968.  
  24969.     ^ true! !
  24970.  
  24971. !Component class methodsFor: 'all' stamp: 'di 4/18/1998 11:08'!
  24972. addSlotNamed: aName
  24973.     (self allInstVarNames includes: aName) ifTrue: [self error: 'Duplicate slot name'].
  24974.     self addInstVarName: aName.
  24975. ! !
  24976.  
  24977. !Component class methodsFor: 'all' stamp: 'di 5/2/1998 10:40'!
  24978. compileAccessorsFor: varName
  24979.     "This should come around and invoke the new implementation
  24980.     inherited from Player (instance)"
  24981.     ^ self basicNew compileAccessorsFor: varName
  24982. ! !
  24983.  
  24984. !Component class methodsFor: 'all' stamp: 'di 4/13/98 12:15'!
  24985. includeInNewMorphMenu
  24986.     "Only include instances of subclasses of me"
  24987.     ^ self ~~ Component! !
  24988.  
  24989. !Component class methodsFor: 'all' stamp: 'di 5/3/1998 19:55'!
  24990. wantsChangeSetLogging
  24991.     "Log changes for Component itself, but not for automatically-created subclasses like Component1, Component2"
  24992.  
  24993.     "^ self == Component or:
  24994.         [(self class name beginsWith: 'Component') not]"
  24995.  
  24996.     "Log everything for now"
  24997.     false ifTrue: [self halt  "DONT FORGET TO REORDER FILEOUT"].
  24998.     ^ true! !
  24999. Component subclass: #Component1
  25000.     instanceVariableNames: 'printComponent1value listComponent1selectedItem functionComponent1output listComponent2selectedItem functionComponent2output functionComponent3output listComponent3selectedItem functionComponent4output listComponent4selectedItem functionComponent5output '
  25001.     classVariableNames: ''
  25002.     poolDictionaries: ''
  25003.     category: 'Morphic-Components-Demo'!
  25004.  
  25005. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:31'!
  25006. functionComponent1output
  25007.     ^functionComponent1output! !
  25008.  
  25009. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:31'!
  25010. functionComponent1outputSet: newValue
  25011.     functionComponent1output _ newValue.
  25012.     self changed: #functionComponent1output! !
  25013.  
  25014. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:35'!
  25015. functionComponent2output
  25016.     ^functionComponent2output! !
  25017.  
  25018. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:35'!
  25019. functionComponent2outputSet: newValue
  25020.     functionComponent2output _ newValue.
  25021.     self changed: #functionComponent2output! !
  25022.  
  25023. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:35'!
  25024. functionComponent3output
  25025.     ^functionComponent3output! !
  25026.  
  25027. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:35'!
  25028. functionComponent3outputSet: newValue
  25029.     functionComponent3output _ newValue.
  25030.     self changed: #functionComponent3output! !
  25031.  
  25032. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:42'!
  25033. functionComponent4output
  25034.     ^functionComponent4output! !
  25035.  
  25036. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:42'!
  25037. functionComponent4outputSet: newValue
  25038.     functionComponent4output _ newValue.
  25039.     self changed: #functionComponent4output! !
  25040.  
  25041. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:49'!
  25042. functionComponent5output
  25043.     ^functionComponent5output! !
  25044.  
  25045. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:49'!
  25046. functionComponent5outputSet: newValue
  25047.     functionComponent5output _ newValue.
  25048.     self changed: #functionComponent5output! !
  25049.  
  25050. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:30'!
  25051. listComponent1selectedItem
  25052.     ^listComponent1selectedItem! !
  25053.  
  25054. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:30'!
  25055. listComponent1selectedItemSet: newValue
  25056.     listComponent1selectedItem _ newValue.
  25057.     self changed: #listComponent1selectedItem! !
  25058.  
  25059. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:32'!
  25060. listComponent2selectedItem
  25061.     ^listComponent2selectedItem! !
  25062.  
  25063. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:32'!
  25064. listComponent2selectedItemSet: newValue
  25065.     listComponent2selectedItem _ newValue.
  25066.     self changed: #listComponent2selectedItem! !
  25067.  
  25068. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:41'!
  25069. listComponent3selectedItem
  25070.     ^listComponent3selectedItem! !
  25071.  
  25072. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:41'!
  25073. listComponent3selectedItemSet: newValue
  25074.     listComponent3selectedItem _ newValue.
  25075.     self changed: #listComponent3selectedItem! !
  25076.  
  25077. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:48'!
  25078. listComponent4selectedItem
  25079.     ^listComponent4selectedItem! !
  25080.  
  25081. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:48'!
  25082. listComponent4selectedItemSet: newValue
  25083.     listComponent4selectedItem _ newValue.
  25084.     self changed: #listComponent4selectedItem! !
  25085.  
  25086. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:29'!
  25087. printComponent1value
  25088.     ^printComponent1value! !
  25089.  
  25090. !Component1 methodsFor: 'view access' stamp: 'di 5/8/1998 23:29'!
  25091. printComponent1valueSet: newValue
  25092.     printComponent1value _ newValue.
  25093.     self changed: #printComponent1value! !
  25094.  
  25095.  
  25096. !Component1 methodsFor: 'functions' stamp: 'di 5/8/1998 23:31'!
  25097. functionComponent1a: a 
  25098.     ^ SystemOrganization listAtCategoryNamed: a! !
  25099.  
  25100. !Component1 methodsFor: 'functions' stamp: 'di 5/8/1998 23:36'!
  25101. functionComponent2a: a 
  25102.     ^ Smalltalk at: a! !
  25103.  
  25104. !Component1 methodsFor: 'functions' stamp: 'di 5/8/1998 23:36'!
  25105. functionComponent3a: a 
  25106.     ^ a organization categories! !
  25107.  
  25108. !Component1 methodsFor: 'functions' stamp: 'di 5/8/1998 23:43'!
  25109. functionComponent4a: a b: b 
  25110.     ^ a organization listAtCategoryNamed: b! !
  25111.  
  25112. !Component1 methodsFor: 'functions' stamp: 'di 5/8/1998 23:51'!
  25113. functionComponent5a: a b: b 
  25114.     ^ a sourceCodeAt: b! !
  25115. PasteUpMorph subclass: #ComponentLayout
  25116.     instanceVariableNames: ''
  25117.     classVariableNames: ''
  25118.     poolDictionaries: ''
  25119.     category: 'Morphic-Components'!
  25120.  
  25121. !ComponentLayout methodsFor: 'all' stamp: 'di 5/3/1998 10:17'!
  25122. acceptDroppingMorph: aMorph event: evt
  25123.     "Eschew all of PasteUp's mechanism for now"
  25124.  
  25125.     self addMorph: aMorph.
  25126. ! !
  25127.  
  25128. !ComponentLayout methodsFor: 'all' stamp: 'di 5/3/1998 09:44'!
  25129. addCustomMenuItems: menu hand: aHandMorph
  25130.  
  25131.     super addCustomMenuItems: menu hand: aHandMorph.
  25132.     menu addLine.
  25133.     menu add: 'inspect model in morphic' action: #inspectModelInMorphic! !
  25134.  
  25135. !ComponentLayout methodsFor: 'all' stamp: 'di 5/5/1998 01:02'!
  25136. allKnownNames
  25137.     ^ (self submorphs collect: [:m | m knownName] thenSelect: [:m | m ~~ nil])! !
  25138.  
  25139. !ComponentLayout methodsFor: 'all' stamp: 'di 5/2/1998 21:36'!
  25140. createCustomModel
  25141.     "Create a model object for this world if it does not yet have one.
  25142.     The default model for an EditView is a Component."
  25143.  
  25144.     model == nil ifFalse: [^ self].  "already has a model"
  25145.     model _ Component newSubclass new.
  25146. ! !
  25147.  
  25148. !ComponentLayout methodsFor: 'all' stamp: 'di 5/4/1998 08:01'!
  25149. initialize
  25150.     super initialize.
  25151.     self extent: 384@256! !
  25152.  
  25153. !ComponentLayout methodsFor: 'all' stamp: 'di 5/3/1998 09:41'!
  25154. inspectModelInMorphic
  25155.     | insp |
  25156.     insp _ InspectorBrowser openAsMorphOn: self model.
  25157.     self world addMorph: insp; startStepping: insp! !
  25158. MorphicModel subclass: #ComponentLikeModel
  25159.     instanceVariableNames: 'pinSpecs '
  25160.     classVariableNames: ''
  25161.     poolDictionaries: ''
  25162.     category: 'Morphic-Components'!
  25163.  
  25164. !ComponentLikeModel methodsFor: 'initialization' stamp: 'di 5/3/1998 09:24'!
  25165. duplicate: newGuy from: oldGuy
  25166.     "oldGuy has just been duplicated and will stay in this world.  Make sure all the ComponentLikeModel requirements are carried out for the copy.  Ask user to rename it.  "
  25167.  
  25168.     newGuy installModelIn: oldGuy pasteUpMorph.
  25169.     newGuy copySlotMethodsFrom: oldGuy slotName.! !
  25170.  
  25171.  
  25172. !ComponentLikeModel methodsFor: 'compilation' stamp: 'di 5/3/1998 09:25'!
  25173. choosePartName
  25174.     "When I am renamed, get a slot, make default methods, move any existing methods."
  25175.     | old |
  25176.     (self pasteUpMorph model isKindOf: Component) ifTrue:
  25177.         [self knownName ifNil: [^ self nameMeIn: self pasteUpMorph]
  25178.                     ifNotNil: [^ self renameMe]].
  25179.     old _ slotName.
  25180.     super choosePartName.
  25181.     slotName ifNil: [^ self].  "user chose bad slot name"
  25182.     self model: self world model slotName: slotName.
  25183.     old == nil 
  25184.         ifTrue: [self compilePropagationMethods]
  25185.         ifFalse: [self copySlotMethodsFrom: old].
  25186.             "old ones not erased!!"! !
  25187.  
  25188.  
  25189. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/3/1998 22:10'!
  25190. addAddHandMenuItemsForHalo: aMenu hand: aHandMorph
  25191.  
  25192.     super addAddHandMenuItemsForHalo: aMenu hand: aHandMorph.
  25193.     aMenu addLine.
  25194.     aMenu add: 'inspect' action: #inspectMorph.
  25195.     aMenu add: 'delete' action: #dismissMorph! !
  25196.  
  25197. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/1/1998 16:14'!
  25198. addPinFromSpec: pinSpec
  25199.     | pin |
  25200.     pin _ PinMorph new component: self pinSpec: pinSpec.
  25201.     self addMorph: pin.
  25202.     pin placeFromSpec.
  25203.     ^ pin! !
  25204.  
  25205. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/16/1998 16:36'!
  25206. delete
  25207.  
  25208.     (model isKindOf: Component) ifTrue: [^ self deleteComponent].
  25209.     (model isKindOf: MorphicModel) ifFalse: [^ super delete].
  25210.  
  25211.     (PopUpMenu confirm:
  25212. 'Shall I remove the slot ', slotName, '
  25213. along with all associated methods?') ifTrue: [
  25214.         (model class selectors select: [:s | s beginsWith: slotName])
  25215.             do: [:s | model class removeSelector: s].
  25216.         (model class instVarNames includes: slotName)
  25217.             ifTrue: [model class removeInstVarName: slotName].
  25218.     ] ifFalse: [
  25219.         (PopUpMenu confirm:
  25220. '...but should I at least dismiss this morph?
  25221. [choose no to leave everything unchanged]')
  25222.             ifFalse: [^ self]].
  25223.  
  25224.     super delete.
  25225. ! !
  25226.  
  25227. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/2/1998 15:07'!
  25228. deleteComponent
  25229.     model removeDependent: self.
  25230.     self pinsDo: [:pin | pin delete].
  25231.     ^ super delete! !
  25232.  
  25233. !ComponentLikeModel methodsFor: 'components' stamp: 'di 4/29/1998 09:49'!
  25234. extent: newExtent
  25235.     super extent: newExtent.
  25236.     self submorphsDo: [:m | (m isKindOf: PinMorph) ifTrue: [m placeFromSpec]]! !
  25237.  
  25238. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/5/1998 00:57'!
  25239. initComponentIn: aLayout
  25240.     model _ aLayout model.
  25241.     self nameMeIn: aLayout.
  25242.     self color: Color lightCyan.
  25243.     self initPinSpecs.
  25244.     self initFromPinSpecs.
  25245.     self showPins.
  25246.     model addDependent: self! !
  25247.  
  25248. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/1/1998 16:31'!
  25249. initFromPinSpecs
  25250.     "no-op for default"! !
  25251.  
  25252. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/3/1998 20:11'!
  25253. initPinSpecs
  25254.     "no-op for default"
  25255.     pinSpecs _ Array new.
  25256. ! !
  25257.  
  25258. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/3/1998 20:07'!
  25259. justDroppedInto: aMorph event: anEvent
  25260.     | theModel |
  25261.     theModel _ aMorph model.
  25262.     ((aMorph isKindOf: ComponentLayout) 
  25263.         and: [theModel isKindOf: Component]) ifFalse:
  25264.         ["Disconnect prior to removal by move"
  25265.         (theModel isKindOf: Component) ifTrue: [self unwire.  model _ nil].
  25266.         ^ self].
  25267.     theModel == model ifTrue: [^ self  "Presumably just a move"].
  25268.     self initComponentIn: aMorph! !
  25269.  
  25270. !ComponentLikeModel methodsFor: 'components' stamp: 'di 4/26/1998 10:40'!
  25271. nameMeIn: aWorld
  25272.     | stem otherNames i partName className |
  25273.     className _ self class name.
  25274.     stem _ className.
  25275.     (stem size > 5 and: [stem endsWith: 'Morph'])
  25276.         ifTrue: [stem _ stem copyFrom: 1 to: stem size - 5].
  25277.     stem _ stem first asLowercase asString , stem allButFirst.
  25278.     otherNames _ Set newFrom: aWorld allKnownNames.
  25279.     i _ 1.
  25280.     [otherNames includes: (partName _ stem , i printString)]
  25281.         whileTrue: [i _ i + 1].
  25282.     self setNamePropertyTo: partName! !
  25283.  
  25284. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/3/1998 20:18'!
  25285. pinSpecs
  25286.     ^ pinSpecs! !
  25287.  
  25288. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/2/1998 15:09'!
  25289. pinsDo: pinBlock
  25290.     self submorphsDo: [:m | (m isKindOf: PinMorph) ifTrue: [pinBlock value: m]]! !
  25291.  
  25292. !ComponentLikeModel methodsFor: 'components' stamp: 'di 5/3/1998 09:26'!
  25293. renameMe
  25294.     | otherNames newName |
  25295.     otherNames _ Set newFrom: self pasteUpMorph allKnownNames.
  25296.     newName _ FillInTheBlank request: 'Please give this new a name'
  25297.                         initialAnswer: self knownName.
  25298.     newName isEmpty ifTrue: [^ nil].
  25299.     (otherNames includes: newName) ifTrue:
  25300.             [self inform: 'Sorry, that name is already used'. ^ nil].
  25301.     self setNamePropertyTo: newName! !
  25302.  
  25303. !ComponentLikeModel methodsFor: 'components' stamp: 'di 4/29/1998 15:16'!
  25304. showPins
  25305.     "Make up sensitized pinMorphs for each of my interface variables"
  25306.     self pinSpecs do: [:pinSpec | self addPinFromSpec: pinSpec]! !
  25307. MorphicTransform subclass: #CompositeTransform
  25308.     instanceVariableNames: 'globalTransform localTransform '
  25309.     classVariableNames: ''
  25310.     poolDictionaries: ''
  25311.     category: 'Morphic-Support'!
  25312. !CompositeTransform commentStamp: 'di 5/22/1998 16:33' prior: 0!
  25313. A composite transform provides the effect of several levels of coordinate transformations.  This class is a subclass of MorphicTransform, only to inherit some generic transformation methods.  It would be better for both classes to inherit these methods from a common superclass.!
  25314.  
  25315.  
  25316. !CompositeTransform methodsFor: 'initialization' stamp: 'di 3/4/98 19:17'!
  25317. globalTransform: gt localTransform: lt
  25318.     globalTransform _ gt.
  25319.     localTransform _ lt! !
  25320.  
  25321.  
  25322. !CompositeTransform methodsFor: 'testing' stamp: 'di 3/4/98 19:18'!
  25323. isIdentity
  25324.     ^ globalTransform isIdentity and: [localTransform isIdentity]! !
  25325.  
  25326. !CompositeTransform methodsFor: 'testing' stamp: 'di 3/4/98 19:18'!
  25327. isPureTranslation
  25328.     ^ globalTransform isPureTranslation and: [localTransform isPureTranslation]! !
  25329.  
  25330.  
  25331. !CompositeTransform methodsFor: 'transformations' stamp: 'di 3/4/98 19:20'!
  25332. invert: aPoint
  25333.     ^ globalTransform invert: (localTransform transform: aPoint)! !
  25334.  
  25335. !CompositeTransform methodsFor: 'transformations' stamp: 'di 3/4/98 19:20'!
  25336. transform: aPoint
  25337.     ^ localTransform transform: (globalTransform transform: aPoint)! !
  25338. CharacterScanner subclass: #CompositionScanner
  25339.     instanceVariableNames: 'spaceX spaceIndex lineHeight baseline lineHeightAtSpace baselineAtSpace '
  25340.     classVariableNames: ''
  25341.     poolDictionaries: 'TextConstants '
  25342.     category: 'Graphics-Support'!
  25343. !CompositionScanner commentStamp: 'di 5/22/1998 16:33' prior: 0!
  25344. CompositionScanner comment:
  25345. 'CompositionScanners are used to measure text and determine where line breaks and space padding should occur.'!
  25346.  
  25347.  
  25348. !CompositionScanner methodsFor: 'initialize-release'!
  25349. in: aParagraph 
  25350.     "Initialize the paragraph to be scanned as the argument, aParagraph. Set 
  25351.     the composition frame for the paragraph."
  25352.  
  25353.     super initializeFromParagraph: aParagraph clippedBy: aParagraph clippingRectangle! !
  25354.  
  25355.  
  25356. !CompositionScanner methodsFor: 'accessing'!
  25357. rightX
  25358.     "Meaningful only when a line has just been composed -- refers to the 
  25359.     line most recently composed. This is a subtrefuge to allow for easy 
  25360.     resizing of a composition rectangle to the width of the maximum line. 
  25361.     Useful only when there is only one line in the form or when each line 
  25362.     is terminated by a carriage return. Handy for sizing menus and lists."
  25363.  
  25364.     ^spaceX! !
  25365.  
  25366.  
  25367. !CompositionScanner methodsFor: 'scanning' stamp: 'di 11/29/97 08:46'!
  25368. composeFrom: startIndex inRectangle: lineRectangle
  25369.     firstLine: firstLine leftSide: leftSide rightSide: rightSide
  25370.     "Answer an instance of TextLineInterval that represents the next line in the paragraph."
  25371.     | runLength done stopCondition |
  25372.     "Set up margins"
  25373.     leftMargin _ lineRectangle left.
  25374.     leftSide ifTrue: [leftMargin _ leftMargin +
  25375.                         (firstLine ifTrue: [textStyle firstIndent]
  25376.                                 ifFalse: [textStyle restIndent])].
  25377.     spaceX _ destX _ leftMargin.
  25378.     rightMargin _ lineRectangle right.
  25379.     rightSide ifTrue: [rightMargin _ rightMargin - textStyle rightIndent].
  25380.     lastIndex _ startIndex.    "scanning sets last index"
  25381.     destY _ lineRectangle top.
  25382.     lineHeight _ baseline _ 0.  "Will be increased by setFont"
  25383.     self setStopConditions.    "also sets font"
  25384.     runLength _ text runLengthFor: startIndex.
  25385.     runStopIndex _ (lastIndex _ startIndex) + (runLength - 1).
  25386.     line _ (TextLine start: lastIndex stop: 0 internalSpaces: 0 paddingWidth: 0)
  25387.                 rectangle: lineRectangle;
  25388.                 leftMargin: leftMargin.
  25389.     
  25390.     spaceCount _ 0.
  25391.     done _ false.
  25392.     [done]
  25393.         whileFalse: 
  25394.             [stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex
  25395.                 in: text string rightX: rightMargin stopConditions: stopConditions
  25396.                 kern: kern displaying: false.
  25397.             "See setStopConditions for stopping conditions for composing."
  25398.             (self perform: stopCondition)
  25399.                 ifTrue: [^ line lineHeight: lineHeight + textStyle leading
  25400.                             baseline: baseline + textStyle leading]]! !
  25401.  
  25402. !CompositionScanner methodsFor: 'scanning' stamp: 'di 10/29/97 12:17'!
  25403. composeLine: lineIndex fromCharacterIndex: startIndex inParagraph: aParagraph 
  25404.     "Answer an instance of TextLineInterval that represents the next line in the paragraph."
  25405.     | runLength done stopCondition |
  25406.     spaceX _ destX _ leftMargin _ aParagraph leftMarginForCompositionForLine: lineIndex.
  25407.     destY _ 0.
  25408.     rightMargin _ aParagraph rightMarginForComposition.
  25409.     leftMargin >= rightMargin ifTrue: [self error: 'No room between margins to compose'].
  25410.     lastIndex _ startIndex.    "scanning sets last index"
  25411.     lineHeight _ textStyle lineGrid.  "may be increased by setFont:..."
  25412.     baseline _ textStyle baseline.
  25413.     self setStopConditions.    "also sets font"
  25414.     runLength _ text runLengthFor: startIndex.
  25415.     runStopIndex _ (lastIndex _ startIndex) + (runLength - 1).
  25416.     line _ TextLineInterval
  25417.         start: lastIndex
  25418.         stop: 0
  25419.         internalSpaces: 0
  25420.         paddingWidth: 0.
  25421.     spaceCount _ 0.
  25422.     done _ false.
  25423.     [done]
  25424.         whileFalse: 
  25425.             [stopCondition _ self scanCharactersFrom: lastIndex to: runStopIndex
  25426.                 in: text string rightX: rightMargin stopConditions: stopConditions
  25427.                 kern: kern displaying: false.
  25428.             "See setStopConditions for stopping conditions for composing."
  25429.             (self perform: stopCondition)
  25430.                 ifTrue: [^line lineHeight: lineHeight + textStyle leading
  25431.                             baseline: baseline + textStyle leading]]! !
  25432.  
  25433. !CompositionScanner methodsFor: 'scanning' stamp: 'di 10/24/97 09:15'!
  25434. setActualFont: aFont
  25435.     "Keep track of max height and ascent for auto lineheight"
  25436.     | descent |
  25437.     super setActualFont: aFont.
  25438.     lineHeight == nil
  25439.         ifTrue: [descent _ font descent.
  25440.                 baseline _ font ascent.
  25441.                 lineHeight _ baseline + descent]
  25442.         ifFalse: [descent _ lineHeight - baseline max: font descent.
  25443.                 baseline _ baseline max: font ascent.
  25444.                 lineHeight _ lineHeight max: baseline + descent]! !
  25445.  
  25446.  
  25447. !CompositionScanner methodsFor: 'stop conditions'!
  25448. cr
  25449.     "Answer true. Set up values for the text line interval currently being 
  25450.     composed."
  25451.  
  25452.     line stop: lastIndex.
  25453.     spaceX _ destX.
  25454.     line paddingWidth: rightMargin - destX.
  25455.     ^true! !
  25456.  
  25457. !CompositionScanner methodsFor: 'stop conditions' stamp: 'di 11/10/97 10:35'!
  25458. crossedX
  25459.     "There is a word that has fallen across the right edge of the composition 
  25460.     rectangle. This signals the need for wrapping which is done to the last 
  25461.     space that was encountered, as recorded by the space stop condition."
  25462.  
  25463.     spaceCount >= 1 ifTrue:
  25464.         ["The common case. First back off to the space at which we wrap."
  25465.         line stop: spaceIndex.
  25466.         lineHeight _ lineHeightAtSpace.
  25467.         baseline _ baselineAtSpace.
  25468.         spaceCount _ spaceCount - 1.
  25469.         spaceIndex _ spaceIndex - 1.
  25470.  
  25471.         "Check to see if any spaces preceding the one at which we wrap.
  25472.             Double space after punctuation, most likely."
  25473.         [(spaceCount > 1 and: [(text at: spaceIndex) = Space])]
  25474.             whileTrue:
  25475.                 [spaceCount _ spaceCount - 1.
  25476.                 "Account for backing over a run which might
  25477.                     change width of space."
  25478.                 font _ text fontAt: spaceIndex withStyle: textStyle.
  25479.                 spaceIndex _ spaceIndex - 1.
  25480.                 spaceX _ spaceX - (font widthOf: Space)].
  25481.         line paddingWidth: rightMargin - spaceX.
  25482.         line internalSpaces: spaceCount]
  25483.     ifFalse:
  25484.         ["Neither internal nor trailing spaces -- almost never happens."
  25485.         lastIndex _ lastIndex - 1.
  25486.         [destX <= rightMargin]
  25487.             whileFalse:
  25488.                 [destX _ destX - (font widthOf: (text at: lastIndex)).
  25489.                 lastIndex _ lastIndex - 1].
  25490.         spaceX _ destX.
  25491.         line paddingWidth: rightMargin - destX.
  25492.         line stop: (lastIndex max: line first)].
  25493.     ^true! !
  25494.  
  25495. !CompositionScanner methodsFor: 'stop conditions'!
  25496. endOfRun
  25497.     "Answer true if scanning has reached the end of the paragraph. 
  25498.     Otherwise step conditions (mostly install potential new font) and answer 
  25499.     false."
  25500.  
  25501.     | runLength |
  25502.     lastIndex = text size
  25503.     ifTrue:    [line stop: lastIndex.
  25504.             spaceX _ destX.
  25505.             line paddingWidth: rightMargin - destX.
  25506.             ^true]
  25507.     ifFalse:    [runLength _ (text runLengthFor: (lastIndex _ lastIndex + 1)).
  25508.             runStopIndex _ lastIndex + (runLength - 1).
  25509.             self setStopConditions.
  25510.             ^false]
  25511. ! !
  25512.  
  25513. !CompositionScanner methodsFor: 'stop conditions' stamp: 'di 11/13/97 12:13'!
  25514. placeEmbeddedObject: anchoredMorph
  25515.     | descent |
  25516.     (super placeEmbeddedObject: anchoredMorph) ifFalse: [^ false].
  25517.     descent _ lineHeight - baseline.
  25518.     lineHeight _ lineHeight max: anchoredMorph height.
  25519.     baseline _ lineHeight - descent.
  25520.     ^ true! !
  25521.  
  25522. !CompositionScanner methodsFor: 'stop conditions'!
  25523. setStopConditions
  25524.     "Set the font and the stop conditions for the current run."
  25525.     
  25526.     self setFont! !
  25527.  
  25528. !CompositionScanner methodsFor: 'stop conditions' stamp: 'di 11/5/97 07:46'!
  25529. space
  25530.     "Record left x and character index of the space character just encounted. 
  25531.     Used for wrap-around. Answer whether the character has crossed the 
  25532.     right edge of the composition rectangle of the paragraph."
  25533.  
  25534.     spaceX _ destX.
  25535.     destX _ spaceX + spaceWidth.
  25536.     spaceIndex _ lastIndex.
  25537.     lineHeightAtSpace _ lineHeight.
  25538.     baselineAtSpace _ baseline.
  25539.     lastIndex _ lastIndex + 1.
  25540.     spaceCount _ spaceCount + 1.
  25541.     destX > rightMargin ifTrue:     [^self crossedX].
  25542.     ^false
  25543. ! !
  25544.  
  25545. !CompositionScanner methodsFor: 'stop conditions'!
  25546. tab
  25547.     "Advance destination x according to tab settings in the paragraph's 
  25548.     textStyle. Answer whether the character has crossed the right edge of 
  25549.     the composition rectangle of the paragraph."
  25550.  
  25551.     destX _ textStyle
  25552.                 nextTabXFrom: destX leftMargin: leftMargin rightMargin: rightMargin.
  25553.     destX > rightMargin ifTrue:    [^self crossedX].
  25554.     lastIndex _ lastIndex + 1.
  25555.     ^false
  25556. ! !
  25557. AlignmentMorph subclass: #CompoundTileMorph
  25558.     instanceVariableNames: 'type testPart yesPart noPart '
  25559.     classVariableNames: ''
  25560.     poolDictionaries: ''
  25561.     category: 'Morphic-Scripting-Tiles'!
  25562. !CompoundTileMorph commentStamp: 'di 5/22/1998 16:33' prior: 0!
  25563. CompoundTileMorph comment:
  25564. 'A statement with other whole statements inside it.  If-Then.  Test.'!
  25565.  
  25566.  
  25567. !CompoundTileMorph methodsFor: 'all'!
  25568. acceptDroppingMorph: aMorph event: evt
  25569.     "Forward the dropped morph to the appropriate part."
  25570.  
  25571.     (self targetPartFor: aMorph) acceptDroppingMorph: aMorph event: evt.
  25572. ! !
  25573.  
  25574. !CompoundTileMorph methodsFor: 'all'!
  25575. codeString
  25576.  
  25577.     | s |
  25578.     s _ WriteStream on: ''.
  25579.     self storeCodeOn: s.
  25580.     ^ s contents
  25581. ! !
  25582.  
  25583. !CompoundTileMorph methodsFor: 'all' stamp: 'di 10/17/97 21:31'!
  25584. enclosingEditor
  25585.     "Return the next scriptor outward in the containment hierarchy"
  25586.     | current |
  25587.     current _ owner.
  25588.     [current == nil] whileFalse:
  25589.         [((current isKindOf: ScriptEditorMorph)
  25590.                 or: [current isKindOf: CompoundTileMorph])
  25591.             ifTrue: [^ current].
  25592.         current _ current owner].
  25593.     ^ nil! !
  25594.  
  25595. !CompoundTileMorph methodsFor: 'all' stamp: 'di 10/17/97 21:36'!
  25596. handlesMouseOver: evt
  25597.  
  25598.     ^ true
  25599. ! !
  25600.  
  25601. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 5/13/1998 14:49'!
  25602. initialize
  25603.  
  25604.     | r |
  25605.     super initialize.
  25606.     self color: Color orange muchLighter.
  25607.     self borderWidth: 1.
  25608.     self inset: 2.
  25609.     self orientation: #vertical.
  25610.  
  25611.     r _ AlignmentMorph newRow color: color; inset: 0.
  25612.     r setProperty: #demandsBoolean toValue: true.
  25613.     r addMorphBack: (Morph new color: color; extent: 2@5).  "spacer"
  25614.     r addMorphBack: (StringMorph new contents: 'Test').
  25615.     r addMorphBack: (Morph new color: color; extent: 5@5).  "spacer"
  25616.     r addMorphBack: (testPart _ BooleanScriptEditor new borderWidth: 0; inset: 1).
  25617.     testPart color: Color transparent.
  25618.     self addMorphBack: r.
  25619.  
  25620.     r _ AlignmentMorph newRow color: color; inset: 0.
  25621.     r addMorphBack: (Morph new color: color; extent: 30@5).  "spacer"
  25622.     r addMorphBack: (StringMorph new contents: 'Yes').
  25623.     r addMorphBack: (Morph new color: color; extent: 5@5).  "spacer"
  25624.     r addMorphBack: (yesPart _ ScriptEditorMorph new borderWidth: 0; inset: 2).
  25625.     yesPart color: Color transparent.
  25626.     self addMorphBack: r.
  25627.  
  25628.     r _ AlignmentMorph newRow color: color; inset: 0.
  25629.     r addMorphBack: (Morph new color: color; extent: 35@5).  "spacer"
  25630.     r addMorphBack: (StringMorph new contents: 'No').
  25631.     r addMorphBack: (Morph new color: color; extent: 5@5).  "spacer"
  25632.     r addMorphBack: (noPart _ ScriptEditorMorph new borderWidth: 0; inset: 2).
  25633.     noPart color: Color transparent.
  25634.     self addMorphBack: r.
  25635.  
  25636.     self extent: 5@5.  "will grow to fit"
  25637. ! !
  25638.  
  25639. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 10/18/97 18:03'!
  25640. install
  25641.     "Backstop for obscure cases"! !
  25642.  
  25643. !CompoundTileMorph methodsFor: 'all' stamp: 'tk 10/1/97 18:25'!
  25644. isTileLike
  25645.     "Can be dropped into a script"
  25646.     ^ true! !
  25647.  
  25648. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 10/13/97 21:25'!
  25649. markEdited
  25650.     "Pertains only when the test is outside a script?!!"
  25651. ! !
  25652.  
  25653. !CompoundTileMorph methodsFor: 'all' stamp: 'jm 10/18/97 21:03'!
  25654. mouseEnter: evt
  25655.     "Resume drop-tracking in enclosing editor"
  25656.     | ed |
  25657.     (ed _ self enclosingEditor) ifNotNil:
  25658.         [ed mouseLeave: evt]! !
  25659.  
  25660. !CompoundTileMorph methodsFor: 'all' stamp: 'jm 10/18/97 21:02'!
  25661. mouseLeave: evt
  25662.     "Resume drop-tracking in enclosing editor"
  25663.     | ed |
  25664.     (ed _ self enclosingEditor) ifNotNil:
  25665.         [ed mouseEnter: evt]! !
  25666.  
  25667. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 2/16/98 03:40'!
  25668. player
  25669.     ^ nil! !
  25670.  
  25671. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 2/1/98 16:40'!
  25672. prepareToUndoDropOf: aMorph
  25673.     "needs to be here, as a no-op, owing to being hit obscurely on occasion"! !
  25674.  
  25675. !CompoundTileMorph methodsFor: 'all' stamp: 'di 10/17/97 16:31'!
  25676. resultType
  25677.     ^ #command! !
  25678.  
  25679. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 5/13/1998 15:19'!
  25680. rowOfRightTypeFor: aLayoutMorph forActor: anActor
  25681.     aLayoutMorph demandsBoolean ifTrue:
  25682.         [^ self error: 'oops, cannot do that, please close this'].
  25683.     ^ self! !
  25684.  
  25685. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 10/13/97 21:23'!
  25686. scriptEdited
  25687.      "Pertains only when the test is outside a script?!!"! !
  25688.  
  25689. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 10/13/97 21:23'!
  25690. scriptee
  25691.      "Pertains only when the test is outside a script?!!"
  25692.     ^ nil! !
  25693.  
  25694. !CompoundTileMorph methodsFor: 'all' stamp: 'jm 11/3/97 16:37'!
  25695. storeCodeBlockFor: scriptPart on: aStream
  25696.  
  25697.     | lastTile |
  25698.     lastTile _ nil.
  25699.     scriptPart allMorphsDo: [:m |
  25700.         (m isKindOf: TileMorph) ifTrue: [
  25701.             (self tile: m isOnLineAfter: lastTile) ifTrue: [
  25702.                 lastTile ~~ nil ifTrue: [aStream nextPut: $.; cr].
  25703.                 aStream tab; tab.
  25704.             ] ifFalse: [
  25705.                 (lastTile ~= nil) ifTrue: [aStream space]].
  25706.             m storeCodeOn: aStream.
  25707.             lastTile _ m]].
  25708. ! !
  25709.  
  25710. !CompoundTileMorph methodsFor: 'all' stamp: 'jm 11/3/97 16:30'!
  25711. storeCodeOn: aStream
  25712.  
  25713.     aStream nextPut: $(.
  25714.     testPart storeCodeOn: aStream.
  25715.     aStream nextPut: $); cr; tab; nextPutAll: 'ifTrue: ['; cr.
  25716.     self storeCodeBlockFor: yesPart on: aStream.
  25717.     aStream nextPut: $]; cr; tab; nextPutAll: 'ifFalse: ['; cr.
  25718.     self storeCodeBlockFor: noPart on: aStream.
  25719.     aStream nextPut: $]; cr.
  25720. ! !
  25721.  
  25722. !CompoundTileMorph methodsFor: 'all'!
  25723. targetPartFor: aMorph
  25724.     "Return the row into which the given morph should be inserted."
  25725.  
  25726.     | centerY |
  25727.     centerY _ aMorph fullBounds center y.
  25728.     (Array with: testPart with: yesPart with: noPart) do: [:m |
  25729.         (centerY <= m bounds bottom) ifTrue: [^ m]].
  25730.     ^ noPart
  25731. ! !
  25732.  
  25733. !CompoundTileMorph methodsFor: 'all' stamp: 'di 5/6/1998 21:10'!
  25734. tile: tile isOnLineAfter: previousTile
  25735.     "Return true if the given tile is not on the same line at the previous tile or if the previous tile is nil."
  25736.  
  25737.     | tileRow previousRow |
  25738.     previousTile ifNil: [^ true].
  25739.     tileRow _ tile owner.
  25740.     [tileRow isMemberOf: AlignmentMorph]
  25741.         whileFalse: [tileRow _ tileRow owner].  "find the owning row"
  25742.     previousRow _ previousTile owner.
  25743.     [previousRow isMemberOf: AlignmentMorph]
  25744.         whileFalse: [previousRow _ previousRow owner].  "find the owning row"
  25745.     ^ tileRow ~~ previousRow
  25746. ! !
  25747.  
  25748. !CompoundTileMorph methodsFor: 'all' stamp: 'tk 10/10/97 17:28'!
  25749. tileRows
  25750.     "See if this works for insertion"
  25751.     ^ Array with: (Array with: self fullCopy)! !
  25752.  
  25753. !CompoundTileMorph methodsFor: 'all' stamp: 'sw 10/13/97 20:25'!
  25754. topEditor
  25755.     | editor |
  25756.     editor _ self outermostMorphThat: [:m | (m isKindOf: ScriptEditorMorph) or:
  25757.          [m isKindOf: CompoundTileMorph]].
  25758.     ^ editor ifNil: [self] ifNotNil: [editor]! !
  25759.  
  25760. !CompoundTileMorph methodsFor: 'all'!
  25761. type
  25762.  
  25763.     ^ #compound
  25764. ! !
  25765.  
  25766. !CompoundTileMorph methodsFor: 'all'!
  25767. wantsDroppedMorph: aMorph event: evt
  25768.  
  25769.     ^ (aMorph isKindOf: TileMorph) or:
  25770.        [(aMorph isKindOf: ScriptEditorMorph) or:
  25771.        [(aMorph isKindOf: CompoundTileMorph) or:
  25772.        [aMorph isKindOf: CommandTilesMorph]]]
  25773. ! !
  25774.  
  25775. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  25776.  
  25777. CompoundTileMorph class
  25778.     instanceVariableNames: ''!
  25779.  
  25780. !CompoundTileMorph class methodsFor: 'instance creation' stamp: 'di 6/22/97 09:07'!
  25781. includeInNewMorphMenu
  25782.     "Not to be instantiated from the menu"
  25783.     ^ false! !
  25784. Object subclass: #ConnectionQueue
  25785.     instanceVariableNames: 'portNumber maxQueueLength connections accessSema socket process '
  25786.     classVariableNames: ''
  25787.     poolDictionaries: ''
  25788.     category: 'System-Network'!
  25789. !ConnectionQueue commentStamp: 'di 5/22/1998 16:33' prior: 0!
  25790. A ConnectionQueue listens on a given port number and collects a queue of client connections. In order to handle state changes quickly, a ConnectionQueue has its own process that: (a) tries to keep a socket listening on the port whenever the queue isn't already full of connections and (b) prunes stale connections out of the queue to make room for fresh ones.
  25791. !
  25792.  
  25793.  
  25794. !ConnectionQueue methodsFor: 'public' stamp: 'jm 3/10/98 17:31'!
  25795. connectionCount
  25796.     "Return an estimate of the number of currently queued connections. This is only an estimate since a new connection could be made, or an existing one aborted, at any moment."
  25797.  
  25798.     | count |
  25799.     self pruneStaleConnections.
  25800.     accessSema critical: [count _ connections size].
  25801.     ^ count
  25802. ! !
  25803.  
  25804. !ConnectionQueue methodsFor: 'public' stamp: 'jm 3/9/98 14:34'!
  25805. destroy
  25806.     "Terminate the listener process and destroy all sockets in my possesion."
  25807.  
  25808.     process ifNotNil: [
  25809.         process terminate.
  25810.         process _ nil].
  25811.     socket ifNotNil: [
  25812.         socket destroy.
  25813.         socket _ nil].
  25814.     connections do: [:s | s destroy].
  25815.     connections _ OrderedCollection new.
  25816. ! !
  25817.  
  25818. !ConnectionQueue methodsFor: 'public' stamp: 'jm 3/10/98 09:18'!
  25819. getConnectionOrNil
  25820.     "Return a connected socket, or nil if no connection has been established."
  25821.  
  25822.     | result |
  25823.     accessSema critical: [
  25824.         connections isEmpty
  25825.             ifTrue: [result _ nil]
  25826.             ifFalse: [
  25827.                 result _ connections removeFirst.
  25828.                 ((result isValid) and: [result isConnected]) ifFalse: [  "stale connection"
  25829.                     result destroy.
  25830.                     result _ nil]]].
  25831.     ^ result
  25832. ! !
  25833.  
  25834.  
  25835. !ConnectionQueue methodsFor: 'private' stamp: 'jm 3/10/98 11:07'!
  25836. initPortNumber: anInteger queueLength: queueLength
  25837.     "Private!! Initialize the receiver to listen on the given port number. Up to queueLength connections will be queued."
  25838.  
  25839.     portNumber _ anInteger.
  25840.     maxQueueLength _ queueLength.
  25841.     connections _ OrderedCollection new.
  25842.     accessSema _ Semaphore forMutualExclusion.
  25843.     socket _ nil.
  25844.     process _ [self listenLoop] newProcess.
  25845.     process priority: Processor highIOPriority.
  25846.     process resume.
  25847. ! !
  25848.  
  25849. !ConnectionQueue methodsFor: 'private' stamp: 'jm 3/13/98 14:31'!
  25850. listenLoop
  25851.     "Private!! This loop is run in a separate process. It will establish up to maxQueueLength connections on the given port."
  25852.     "Details: When out of sockets or queue is full, retry more frequently, since a socket may become available, space may open in the queue, or a previously queued connection may be aborted by the client, making it available for a fresh connection."
  25853.  
  25854.     [true] whileTrue: [
  25855.         ((socket == nil) and: [connections size < maxQueueLength]) ifTrue: [
  25856.             "try to create a new socket for listening"
  25857.             socket _ Socket createIfFail: [nil]].
  25858.  
  25859.         socket == nil
  25860.             ifTrue: [(Delay forMilliseconds: 100) wait]
  25861.             ifFalse: [
  25862.                 socket isUnconnected ifTrue: [socket listenOn: portNumber].
  25863.                 socket waitForConnectionUntil: (Socket deadlineSecs: 10).
  25864.                 socket isConnected
  25865.                     ifTrue: [  "connection established"
  25866.                         accessSema critical: [connections addLast: socket].
  25867.                         socket _ nil]
  25868.                     ifFalse: [
  25869.                         (socket isWaitingForConnection or:
  25870.                          [socket isUnconnected])
  25871.                             ifFalse: [socket destroy. socket _ nil]]].  "return to unconnected state"
  25872.  
  25873.         self pruneStaleConnections].
  25874. ! !
  25875.  
  25876. !ConnectionQueue methodsFor: 'private' stamp: 'jm 3/10/98 17:30'!
  25877. pruneStaleConnections
  25878.     "Private!! The client may establish a connection and then disconnect while it is still in the connection queue. This method is called periodically to prune such sockets out of the connection queue and make room for fresh connections."
  25879.  
  25880.     | foundStaleConnection |
  25881.     accessSema critical: [
  25882.         foundStaleConnection _ false.
  25883.         connections do: [:s |
  25884.             s isUnconnected ifTrue: [
  25885.                 s destroy.
  25886.                 foundStaleConnection _ true]].
  25887.         foundStaleConnection ifTrue: [
  25888.             connections _ connections select: [:s | s isValid]]].
  25889. ! !
  25890.  
  25891. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  25892.  
  25893. ConnectionQueue class
  25894.     instanceVariableNames: ''!
  25895.  
  25896. !ConnectionQueue class methodsFor: 'instance creation' stamp: 'jm 3/9/98 14:09'!
  25897. portNumber: anInteger queueLength: queueLength
  25898.  
  25899.     ^ self new initPortNumber: anInteger queueLength: queueLength
  25900. ! !
  25901. InstructionStream subclass: #ContextPart
  25902.     instanceVariableNames: 'stackp '
  25903.     classVariableNames: 'TryPrimitiveMethods TryPrimitiveSelectors '
  25904.     poolDictionaries: ''
  25905.     category: 'Kernel-Methods'!
  25906. !ContextPart commentStamp: 'di 5/22/1998 16:33' prior: 0!
  25907. ContextPart comment:
  25908. 'To the instruction parsing ability of InstructionStream I add the actual semantics for execution. The execution state is stored in the indexable fields of my subclasses. This includes temporary variables and a stack of values used in evaluating expressions. The actual semantics of execution can be found in my category "system simulation" and "instruction decode". These methods exactly parallel the operation of the Smalltalk machine itself.
  25909.     
  25910. The simulator is a group of my methods that do what the Smalltalk interpreter does: execute Smalltalk bytecodes. By adding code to the simulator, you may take statistics on the running of Smalltalk methods. For example,
  25911.     Transcript show: (ContextPart runSimulated: [3 factorial]) printString.'!
  25912.  
  25913.  
  25914. !ContextPart methodsFor: 'accessing'!
  25915. client
  25916.     "Answer the client, that is, the object that sent the message that created this context."
  25917.  
  25918.     ^sender receiver! !
  25919.  
  25920. !ContextPart methodsFor: 'accessing'!
  25921. home
  25922.     "Answer the context in which the receiver was defined."
  25923.  
  25924.     self subclassResponsibility! !
  25925.  
  25926. !ContextPart methodsFor: 'accessing'!
  25927. method
  25928.     "Answer the method of this context."
  25929.  
  25930.     self subclassResponsibility! !
  25931.  
  25932. !ContextPart methodsFor: 'accessing'!
  25933. receiver
  25934.     "Answer the receiver of the message that created this context."
  25935.  
  25936.     self subclassResponsibility! !
  25937.  
  25938. !ContextPart methodsFor: 'accessing'!
  25939. tempAt: index
  25940.     "Answer the value of the temporary variable whose index is the 
  25941.     argument, index."
  25942.  
  25943.     self subclassResponsibility! !
  25944.  
  25945. !ContextPart methodsFor: 'accessing'!
  25946. tempAt: index put: value 
  25947.     "Store the argument, value, as the temporary variable whose index is the 
  25948.     argument, index."
  25949.  
  25950.     self subclassResponsibility! !
  25951.  
  25952.  
  25953. !ContextPart methodsFor: 'instruction decoding'!
  25954. doDup
  25955.     "Simulate the action of a 'duplicate top of stack' bytecode."
  25956.  
  25957.     self push: self top! !
  25958.  
  25959. !ContextPart methodsFor: 'instruction decoding'!
  25960. doPop
  25961.     "Simulate the action of a 'remove top of stack' bytecode."
  25962.  
  25963.     self pop! !
  25964.  
  25965. !ContextPart methodsFor: 'instruction decoding'!
  25966. jump: distance 
  25967.     "Simulate the action of a 'unconditional jump' bytecode whose offset is 
  25968.     the argument, distance."
  25969.  
  25970.     pc _ pc + distance! !
  25971.  
  25972. !ContextPart methodsFor: 'instruction decoding'!
  25973. jump: distance if: condition 
  25974.     "Simulate the action of a 'conditional jump' bytecode whose offset is the 
  25975.     argument, distance, and whose condition is the argument, condition."
  25976.  
  25977.     (self pop eqv: condition) ifTrue: [self jump: distance]! !
  25978.  
  25979. !ContextPart methodsFor: 'instruction decoding'!
  25980. methodReturnConstant: value 
  25981.     "Simulate the action of a 'return constant' bytecode whose value is the 
  25982.     argument, value. This corresponds to a source expression like '^0'."
  25983.  
  25984.     ^self return: value to: self home sender! !
  25985.  
  25986. !ContextPart methodsFor: 'instruction decoding'!
  25987. methodReturnReceiver
  25988.     "Simulate the action of a 'return receiver' bytecode. This corresponds to 
  25989.     the source expression '^self'."
  25990.  
  25991.     ^self return: self receiver to: self home sender! !
  25992.  
  25993. !ContextPart methodsFor: 'instruction decoding'!
  25994. methodReturnTop
  25995.     "Simulate the action of a 'return top of stack' bytecode. This corresponds 
  25996.     to source expressions like '^something'."
  25997.  
  25998.     ^self return: self pop to: self home sender! !
  25999.  
  26000. !ContextPart methodsFor: 'instruction decoding'!
  26001. popIntoLiteralVariable: value 
  26002.     "Simulate the action of bytecode that removes the top of the stack and 
  26003.     stores it into a literal variable of my method."
  26004.  
  26005.     value value: self pop! !
  26006.  
  26007. !ContextPart methodsFor: 'instruction decoding'!
  26008. popIntoReceiverVariable: offset 
  26009.     "Simulate the action of bytecode that removes the top of the stack and 
  26010.     stores it into an instance variable of my receiver."
  26011.  
  26012.     self receiver instVarAt: offset + 1 put: self pop! !
  26013.  
  26014. !ContextPart methodsFor: 'instruction decoding'!
  26015. popIntoTemporaryVariable: offset 
  26016.     "Simulate the action of bytecode that removes the top of the stack and 
  26017.     stores it into one of my temporary variables."
  26018.  
  26019.     self home at: offset + 1 put: self pop! !
  26020.  
  26021. !ContextPart methodsFor: 'instruction decoding'!
  26022. pushActiveContext
  26023.     "Simulate the action of bytecode that pushes the the active context on the 
  26024.     top of its own stack."
  26025.  
  26026.     self push: self! !
  26027.  
  26028. !ContextPart methodsFor: 'instruction decoding'!
  26029. pushConstant: value 
  26030.     "Simulate the action of bytecode that pushes the constant, value, on the 
  26031.     top of the stack."
  26032.  
  26033.     self push: value! !
  26034.  
  26035. !ContextPart methodsFor: 'instruction decoding'!
  26036. pushLiteralVariable: value 
  26037.     "Simulate the action of bytecode that pushes the contents of the literal 
  26038.     variable whose index is the argument, index, on the top of the stack."
  26039.  
  26040.     self push: value value! !
  26041.  
  26042. !ContextPart methodsFor: 'instruction decoding'!
  26043. pushReceiver
  26044.     "Simulate the action of bytecode that pushes the active context's receiver 
  26045.     on the top of the stack."
  26046.  
  26047.     self push: self receiver! !
  26048.  
  26049. !ContextPart methodsFor: 'instruction decoding'!
  26050. pushReceiverVariable: offset 
  26051.     "Simulate the action of bytecode that pushes the contents of the receiver's 
  26052.     instance variable whose index is the argument, index, on the top of the 
  26053.     stack."
  26054.  
  26055.     self push: (self receiver instVarAt: offset + 1)! !
  26056.  
  26057. !ContextPart methodsFor: 'instruction decoding'!
  26058. pushTemporaryVariable: offset 
  26059.     "Simulate the action of bytecode that pushes the contents of the 
  26060.     temporary variable whose index is the argument, index, on the top of 
  26061.     the stack."
  26062.  
  26063.     self push: (self home at: offset + 1)! !
  26064.  
  26065. !ContextPart methodsFor: 'instruction decoding' stamp: 'sn 8/21/97 22:15'!
  26066. send: selector super: superFlag numArgs: numArgs
  26067.     "Simulate the action of bytecodes that send a message with selector, 
  26068.     selector. The argument, superFlag, tells whether the receiver of the 
  26069.     message was specified with 'super' in the source method. The arguments 
  26070.     of the message are found in the top numArgs locations on the stack and 
  26071.     the receiver just below them."
  26072.  
  26073.     | receiver arguments answer |
  26074.     arguments _ Array new: numArgs.
  26075.     numArgs to: 1 by: -1 do: [ :i | arguments at: i put: self pop].
  26076.     receiver _ self pop.
  26077.     (selector == #halt or: [selector == #halt:]) ifTrue:
  26078.         [self error: 'Cant simulate halt.  Proceed to bypass it.'.
  26079.         self push: nil. ^self].
  26080.     selector == #doPrimitive:receiver:args:
  26081.         ifTrue: [answer _ receiver 
  26082.                     doPrimitive: (arguments at: 1)
  26083.                     receiver: (arguments at: 2)
  26084.                     args: (arguments at: 3).
  26085.                 self push: answer.
  26086.                 ^self].
  26087.     ^self send: selector to: receiver with: arguments super: superFlag! !
  26088.  
  26089. !ContextPart methodsFor: 'instruction decoding'!
  26090. storeIntoLiteralVariable: value 
  26091.     "Simulate the action of bytecode that stores the top of the stack into a 
  26092.     literal variable of my method."
  26093.  
  26094.     value value: self top! !
  26095.  
  26096. !ContextPart methodsFor: 'instruction decoding'!
  26097. storeIntoReceiverVariable: offset 
  26098.     "Simulate the action of bytecode that stores the top of the stack into an 
  26099.     instance variable of my receiver."
  26100.  
  26101.     self receiver instVarAt: offset + 1 put: self top! !
  26102.  
  26103. !ContextPart methodsFor: 'instruction decoding'!
  26104. storeIntoTemporaryVariable: offset 
  26105.     "Simulate the action of bytecode that stores the top of the stack into one 
  26106.     of my temporary variables."
  26107.  
  26108.     self home at: offset + 1 put: self top! !
  26109.  
  26110.  
  26111. !ContextPart methodsFor: 'debugger access'!
  26112. depthBelow: aContext
  26113.     "Answer how many calls there are between this and aContext."
  26114.  
  26115.     | this depth |
  26116.     this _ self.
  26117.     depth _ 0.
  26118.     [this == aContext or: [this == nil]]
  26119.         whileFalse:
  26120.             [this _ this sender.
  26121.             depth _ depth + 1].
  26122.     ^depth! !
  26123.  
  26124. !ContextPart methodsFor: 'debugger access'!
  26125. mclass 
  26126.     "Answer the class in which the receiver's method was found."
  26127.  
  26128.     self receiver class selectorAtMethod: self method setClass: [:mclass].
  26129.     ^mclass! !
  26130.  
  26131. !ContextPart methodsFor: 'debugger access'!
  26132. pc
  26133.     "Answer the index of the next bytecode to be executed."
  26134.  
  26135.     ^pc! !
  26136.  
  26137. !ContextPart methodsFor: 'debugger access'!
  26138. release
  26139.     "Remove information from the receiver and all of the contexts on its 
  26140.     sender chain in order to break circularities."
  26141.  
  26142.     self releaseTo: nil! !
  26143.  
  26144. !ContextPart methodsFor: 'debugger access'!
  26145. releaseTo: caller 
  26146.     "Remove information from the receiver and the contexts on its sender 
  26147.     chain up to caller in order to break circularities."
  26148.  
  26149.     | c s |
  26150.     c _ self.
  26151.     [c == nil or: [c == caller]]
  26152.         whileFalse: 
  26153.             [s _ c sender.
  26154.             c singleRelease.
  26155.             c _ s]! !
  26156.  
  26157. !ContextPart methodsFor: 'debugger access'!
  26158. selector
  26159.     "Answer the selector of the method that created the receiver."
  26160.  
  26161.     ^self receiver class 
  26162.         selectorAtMethod: self method 
  26163.         setClass: [:ignored]! !
  26164.  
  26165. !ContextPart methodsFor: 'debugger access'!
  26166. sender
  26167.     "Answer the context that sent the message that created the receiver."
  26168.  
  26169.     ^sender! !
  26170.  
  26171. !ContextPart methodsFor: 'debugger access' stamp: 'tk 4/16/1998 12:00'!
  26172. shortStack
  26173.     "Answer a String showing the top four contexts on my sender chain."
  26174.     | shortStackStream |
  26175.     shortStackStream _ WriteStream on: (String new: 55*10).
  26176.     (self stackOfSize: 10) do: 
  26177.         [:item | shortStackStream print: item; cr].
  26178.     ^shortStackStream contents! !
  26179.  
  26180. !ContextPart methodsFor: 'debugger access'!
  26181. singleRelease
  26182.     "Remove information from the receiver in order to break circularities."
  26183.  
  26184.     stackp == nil ifFalse: [1 to: stackp do: [:i | self at: i put: nil]].
  26185.     sender _ nil! !
  26186.  
  26187. !ContextPart methodsFor: 'debugger access'!
  26188. sourceCode
  26189.     | selector methodClass |
  26190.     selector _ self receiver class selectorAtMethod: self method
  26191.         setClass: [:mclass | methodClass _ mclass].
  26192.     ^ methodClass sourceCodeAt: selector! !
  26193.  
  26194. !ContextPart methodsFor: 'debugger access'!
  26195. stack 
  26196.     "Answer an Array of the contexts on the receiver's sender chain."
  26197.  
  26198.     ^self stackOfSize: 9999! !
  26199.  
  26200. !ContextPart methodsFor: 'debugger access'!
  26201. stackOfSize: limit 
  26202.     "Answer an OrderedCollection of the top 'limit' contexts
  26203.         on the receiver's sender chain."
  26204.  
  26205.     | a stack |
  26206.     stack _ OrderedCollection new.
  26207.     stack addLast: (a _ self).
  26208.     [(a _ a sender) ~~ nil and: [stack size < limit]]
  26209.         whileTrue: [stack addLast: a].
  26210.     ^ stack! !
  26211.  
  26212. !ContextPart methodsFor: 'debugger access'!
  26213. swapSender: coroutine 
  26214.     "Replace the receiver's sender with coroutine and answer the receiver's 
  26215.     previous sender. For use in coroutining."
  26216.  
  26217.     | oldSender |
  26218.     oldSender _ sender.
  26219.     sender _ coroutine.
  26220.     ^oldSender! !
  26221.  
  26222. !ContextPart methodsFor: 'debugger access'!
  26223. tempNames
  26224.     "Answer an OrderedCollection of the names of the receiver's temporary 
  26225.     variables, which are strings."
  26226.  
  26227.     self method setTempNamesIfCached: [:names | ^names].
  26228.     names _ (self mclass compilerClass new
  26229.             parse: self sourceCode
  26230.             in: self mclass
  26231.             notifying: nil) tempNames.
  26232.     self method cacheTempNames: names.
  26233.     ^names! !
  26234.  
  26235. !ContextPart methodsFor: 'debugger access'!
  26236. tempsAndValues
  26237.     "Return a string of the temporary variabls and their current values"
  26238.     | aStream |
  26239.     aStream _ WriteStream on: (String new: 100).
  26240.     self tempNames
  26241.         doWithIndex: [:title :index |
  26242.             aStream nextPutAll: title; nextPut: $:; space; tab.
  26243.             (self tempAt: index) printOn: aStream.
  26244.             aStream cr].
  26245.     ^aStream contents! !
  26246.  
  26247.  
  26248. !ContextPart methodsFor: 'controlling'!
  26249. activateMethod: newMethod withArgs: args receiver: rcvr class: class 
  26250.     "Answer a ContextPart initialized with the arguments."
  26251.  
  26252.     ^MethodContext 
  26253.         sender: self
  26254.         receiver: rcvr
  26255.         method: newMethod
  26256.         arguments: args! !
  26257.  
  26258. !ContextPart methodsFor: 'controlling'!
  26259. blockCopy: numArgs 
  26260.     "Primitive. Distinguish a block of code from its enclosing method by 
  26261.     creating a new BlockContext for that block. The compiler inserts into all 
  26262.     methods that contain blocks the bytecodes to send the message 
  26263.     blockCopy:. Do not use blockCopy: in code that you write!! Only the 
  26264.     compiler can decide to send the message blockCopy:. Fail if numArgs is 
  26265.     not a SmallInteger. Optional. No Lookup. See Object documentation 
  26266.     whatIsAPrimitive."
  26267.  
  26268.     <primitive: 80>
  26269.     ^(BlockContext new: self size)
  26270.         home: self home
  26271.         startpc: pc + 2
  26272.         nargs: numArgs! !
  26273.  
  26274. !ContextPart methodsFor: 'controlling'!
  26275. hasSender: context 
  26276.     "Answer whether the receiver is strictly above context on the stack."
  26277.  
  26278.     | s |
  26279.     self == context ifTrue: [^false].
  26280.     s _ sender.
  26281.     [s == nil]
  26282.         whileFalse: 
  26283.             [s == context ifTrue: [^true].
  26284.             s _ s sender].
  26285.     ^false! !
  26286.  
  26287. !ContextPart methodsFor: 'controlling'!
  26288. pop
  26289.     "Answer the top of the receiver's stack and remove the top of the stack."
  26290.  
  26291.     | val |
  26292.     val _ self at: stackp.
  26293.     self at: stackp put: nil.
  26294.     stackp _ stackp - 1.
  26295.     ^val! !
  26296.  
  26297. !ContextPart methodsFor: 'controlling'!
  26298. push: val 
  26299.     "Push val on the receiver's stack."
  26300.  
  26301.     self at: (stackp _ stackp + 1) put: val! !
  26302.  
  26303. !ContextPart methodsFor: 'controlling'!
  26304. return: value to: sendr 
  26305.     "Simulate the return of value to sendr."
  26306.  
  26307.     self releaseTo: sendr.
  26308.     ^sendr push: value! !
  26309.  
  26310. !ContextPart methodsFor: 'controlling'!
  26311. send: selector to: rcvr with: args super: superFlag 
  26312.     "Simulate the action of sending a message with selector, selector, and 
  26313.     arguments, args, to receiver. The argument, superFlag, tells whether the 
  26314.     receiver of the message was specified with 'super' in the source method."
  26315.  
  26316.     | class meth val |
  26317.     class _ 
  26318.         superFlag
  26319.             ifTrue: [(self method literalAt: self method numLiterals) value superclass]
  26320.             ifFalse: [rcvr class].
  26321.     [class == nil]
  26322.         whileFalse: 
  26323.             [(class includesSelector: selector)
  26324.                 ifTrue: 
  26325.                     [meth _ class compiledMethodAt: selector.
  26326.                     val _ 
  26327.                         self tryPrimitiveFor: meth
  26328.                             receiver: rcvr
  26329.                             args: args.
  26330.                     val == #simulatorFail ifFalse: [^val].
  26331.                     (selector == #doesNotUnderstand: and: [class == Object]) ifTrue:
  26332.                         [ ^ self error: 'Simulated message ' , (args at: 1) selector , ' not understood' ].
  26333.                     ^self
  26334.                         activateMethod: meth
  26335.                         withArgs: args
  26336.                         receiver: rcvr
  26337.                         class: class].
  26338.             class _ class superclass].
  26339.     ^self send: #doesNotUnderstand:
  26340.         to: rcvr
  26341.         with: (Array with: (Message selector: selector arguments: args))
  26342.         super: superFlag! !
  26343.  
  26344. !ContextPart methodsFor: 'controlling'!
  26345. top
  26346.     "Answer the top of the receiver's stack."
  26347.  
  26348.     ^self at: stackp! !
  26349.  
  26350.  
  26351. !ContextPart methodsFor: 'printing'!
  26352. printOn: aStream 
  26353.     | selector class |
  26354.     selector _ 
  26355.         (class _ self receiver class) 
  26356.             selectorAtMethod: self method 
  26357.             setClass: [:mclass].
  26358.     selector == #?
  26359.         ifTrue: 
  26360.             [aStream nextPut: $?; print: self method who.
  26361.             ^self].
  26362.     aStream nextPutAll: class name.
  26363.     mclass == class 
  26364.         ifFalse: 
  26365.             [aStream nextPut: $(.
  26366.             aStream nextPutAll: mclass name.
  26367.             aStream nextPut: $)].
  26368.     aStream nextPutAll: '>>'.
  26369.     aStream nextPutAll: selector! !
  26370.  
  26371.  
  26372. !ContextPart methodsFor: 'system simulation' stamp: 'di 1/5/98 11:20'!
  26373. completeCallee: aContext
  26374.     "Simulate the execution of bytecodes until a return to the receiver."
  26375.     | ctxt current |
  26376.     ctxt _ aContext.
  26377.     [ctxt == current or: [ctxt hasSender: self]]
  26378.         whileTrue: 
  26379.             [current _ ctxt.
  26380.             ctxt _ ctxt step].
  26381.     self stepToSendOrReturn! !
  26382.  
  26383. !ContextPart methodsFor: 'system simulation' stamp: 'di 1/5/98 11:20'!
  26384. runSimulated: aBlock contextAtEachStep: block2
  26385.     "Simulate the execution of the argument, aBlock, until it ends. aBlock 
  26386.     MUST NOT contain an '^'. Evaluate block2 with the current context 
  26387.     prior to each instruction executed. Answer the simulated value of aBlock."
  26388.     | current |
  26389.     aBlock hasMethodReturn
  26390.         ifTrue: [self error: 'simulation of blocks with ^ can run loose'].
  26391.     current _ aBlock.
  26392.     current pushArgs: Array new from: self.
  26393.     [current == self]
  26394.         whileFalse:
  26395.             [block2 value: current.
  26396.             current _ current step].
  26397.     ^self pop! !
  26398.  
  26399. !ContextPart methodsFor: 'system simulation'!
  26400. step
  26401.     "Simulate the execution of the receiver's next bytecode. Answer the 
  26402.     context that would be the active context after this bytecode."
  26403.  
  26404.     ^self interpretNextInstructionFor: self! !
  26405.  
  26406. !ContextPart methodsFor: 'system simulation' stamp: 'sn 8/22/97 21:55'!
  26407. stepToSendOrReturn
  26408.     "Simulate the execution of bytecodes until either sending a message or 
  26409.     returning a value to the receiver (that is, until switching contexts)."
  26410.  
  26411.     [self willReallySend | self willReturn]
  26412.         whileFalse: [self step]! !
  26413.  
  26414.  
  26415. !ContextPart methodsFor: 'private' stamp: 'di 1/4/98 23:16'!
  26416. doPrimitive: primitiveIndex receiver: receiver args: arguments 
  26417.     "Simulate a primitive method whose index is primitiveIndex.  The
  26418.     simulated receiver and arguments are given as arguments to this message."
  26419. "
  26420.     NOTE: In order for perform:WithArguments: to work reliably here,
  26421.     this method must be forced to invoke a large context.  This is done
  26422.     by adding extra temps until the following expression evaluates as true:
  26423.         (ContextPart compiledMethodAt: #doPrimitive:receiver:args:) frameSize > 20
  26424. "
  26425.     | value t1 t2 t3 |
  26426.     "If successful, push result and return resuming context,
  26427.         else ^ #simulatorFail"
  26428.     (primitiveIndex = 80 and: [receiver isKindOf: ContextPart])
  26429.         ifTrue: [^self push: 
  26430.                     ((BlockContext new: receiver size)
  26431.                         home: receiver home
  26432.                         startpc: pc + 2
  26433.                         nargs: (arguments at: 1))].
  26434.     (primitiveIndex = 81 and: [receiver isMemberOf: BlockContext])
  26435.         ifTrue: [^receiver pushArgs: arguments from: self].
  26436.     primitiveIndex = 83 
  26437.         ifTrue: [^ self send: arguments first to: receiver
  26438.                     with: arguments allButFirst
  26439.                     super: false].
  26440.     arguments size > 6 ifTrue: [^#simulatorFail].
  26441.     value _ receiver tryPrimitive: primitiveIndex withArgs: arguments.
  26442.     value == #simulatorFail
  26443.         ifTrue: [^ #simulatorFail]
  26444.         ifFalse: [^ self push: value]! !
  26445.  
  26446. !ContextPart methodsFor: 'private'!
  26447. pop: numObjects toAddable: anAddableCollection
  26448.     "Pop the top numObjects elements from the stack, and store them in
  26449.      anAddableCollection, topmost element last.
  26450.      Do not call directly.  Called indirectly by {1. 2. 3} constructs."
  26451.  
  26452.     | oldTop i |
  26453.     i _ stackp _ (oldTop _ stackp) - numObjects.
  26454.     [(i _ i + 1) <= oldTop] whileTrue:
  26455.         [anAddableCollection add: (self at: i).
  26456.          self at: i put: nil]! !
  26457.  
  26458. !ContextPart methodsFor: 'private'!
  26459. pop: numObjects toIndexable: anIndexableCollection
  26460.     "Pop the top numObjects elements from the stack, and store them in
  26461.      anIndexableCollection, topmost element last.
  26462.      Do not call directly.  Called indirectly by {1. 2. 3} constructs."
  26463.  
  26464.     | oldTop i |
  26465.     i _ stackp _ (oldTop _ stackp) - numObjects.
  26466.     [(i _ i + 1) <= oldTop] whileTrue:
  26467.         [anIndexableCollection at: i-stackp put: (self at: i).
  26468.          self at: i put: nil]! !
  26469.  
  26470. !ContextPart methodsFor: 'private'!
  26471. push: numObjects fromIndexable: anIndexableCollection
  26472.     "Push the elements of anIndexableCollection onto the receiver's stack.
  26473.      Do not call directly.  Called indirectly by {1. 2. 3} constructs."
  26474.  
  26475.     | i |
  26476.     i _ 0.
  26477.     [(i _ i + 1) <= numObjects] whileTrue:
  26478.         [self at: (stackp _ stackp + 1) put: (anIndexableCollection at: i)]! !
  26479.  
  26480. !ContextPart methodsFor: 'private'!
  26481. stackPtr  "For use only by the SystemTracer"
  26482.     ^ stackp! !
  26483.  
  26484. !ContextPart methodsFor: 'private'!
  26485. tryPrimitiveFor: method receiver: receiver args: arguments 
  26486.     "Simulate a primitive method, method for the receiver and arguments given
  26487.     as arguments to this message.  Answer resuming the context if successful, else
  26488.     answer the symbol, #simulatorFail."
  26489.     | flag primIndex |
  26490.     (primIndex _ method primitive) = 0 ifTrue: [^#simulatorFail].
  26491.     ^ self doPrimitive: primIndex receiver: receiver args: arguments! !
  26492.  
  26493. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  26494.  
  26495. ContextPart class
  26496.     instanceVariableNames: ''!
  26497.  
  26498. !ContextPart class methodsFor: 'examples'!
  26499. tallyInstructions: aBlock
  26500.     "This method uses the simulator to count the number of occurrences of
  26501.     each of the Smalltalk instructions executed during evaluation of aBlock.
  26502.     Results appear in order of the byteCode set."
  26503.     | tallies |
  26504.     tallies _ Bag new.
  26505.     thisContext sender
  26506.         runSimulated: aBlock
  26507.         contextAtEachStep:
  26508.             [:current | tallies add: current nextByte].
  26509.     ^tallies sortedElements
  26510.  
  26511.     "ContextPart tallyInstructions: [3.14159 printString]"! !
  26512.  
  26513. !ContextPart class methodsFor: 'examples'!
  26514. tallyMethods: aBlock
  26515.     "This method uses the simulator to count the number of calls on each method
  26516.     invoked in evaluating aBlock. Results are given in order of decreasing counts."
  26517.     | prev tallies |
  26518.     tallies _ Bag new.
  26519.     prev _ aBlock.
  26520.     thisContext sender
  26521.         runSimulated: aBlock
  26522.         contextAtEachStep:
  26523.             [:current |
  26524.             current == prev ifFalse: "call or return"
  26525.                 [prev sender == nil ifFalse: "call only"
  26526.                     [tallies add: current printString].
  26527.                 prev _ current]].
  26528.     ^tallies sortedCounts
  26529.  
  26530.     "ContextPart tallyMethods: [3.14159 printString]"! !
  26531.  
  26532. !ContextPart class methodsFor: 'examples'!
  26533. trace: aBlock        "ContextPart trace: [3 factorial]"
  26534.     "This method uses the simulator to print calls and returned values in the Transcript."
  26535.     | prev |
  26536.     Transcript clear.
  26537.     prev _ aBlock.
  26538.     ^ thisContext sender
  26539.         runSimulated: aBlock
  26540.         contextAtEachStep:
  26541.             [:current |
  26542.             Sensor anyButtonPressed ifTrue: [^ nil].
  26543.             current == prev
  26544.                 ifFalse:
  26545.                     [prev sender == nil ifTrue:  "returning"
  26546.                         [Transcript space; nextPut: $^; print: current top].
  26547.                     Transcript cr;
  26548.                         nextPutAll: (String new: (current depthBelow: aBlock) withAll: $ );
  26549.                         print: current receiver; space; nextPutAll: current selector; endEntry.
  26550.                     prev _ current]]! !
  26551.  
  26552. !ContextPart class methodsFor: 'examples'!
  26553. trace: aBlock onFileNamed: fileName        "ContextPart trace: [3 factorial]"
  26554.     "This method uses the simulator to print calls to a file."
  26555.     | prev f sel |
  26556.     f _ FileStream fileNamed: fileName.
  26557.     prev _ aBlock.
  26558.     thisContext sender
  26559.         runSimulated: aBlock
  26560.         contextAtEachStep:
  26561.             [:current |
  26562.             Sensor anyButtonPressed ifTrue: [^ nil].
  26563.             current == prev
  26564.                 ifFalse:
  26565.                     [f cr;
  26566.                         nextPutAll: (String new: (current depthBelow: aBlock) withAll: $ );
  26567.                         print: current receiver class; space; nextPutAll: (sel _ current selector); flush.
  26568.                     prev _ current.
  26569.                     sel == #error: ifTrue: [self halt]]].
  26570.     f close! !
  26571.  
  26572.  
  26573. !ContextPart class methodsFor: 'simulation'!
  26574. runSimulated: aBlock
  26575.     "Simulate the execution of the argument, current. Answer the result it 
  26576.     returns."
  26577.  
  26578.     ^ thisContext sender
  26579.         runSimulated: aBlock
  26580.         contextAtEachStep: [:ignored]
  26581.  
  26582.     "ContextPart runSimulated: [Pen new defaultNib: 5; go: 100]"! !
  26583. Inspector subclass: #ContextVariablesInspector
  26584.     instanceVariableNames: ''
  26585.     classVariableNames: ''
  26586.     poolDictionaries: ''
  26587.     category: 'Interface-Debugger'!
  26588. !ContextVariablesInspector commentStamp: 'di 5/22/1998 16:33' prior: 0!
  26589. ContextVariablesInspector comment:
  26590. 'I represent a query path into the internal representation of a ContextPart. Typically this is a context at a point in the query path of a Debugger. As a StringHolder, the string I represent is the value of the currently selected variable of the observed temporary variable of the context.'!
  26591.  
  26592.  
  26593. !ContextVariablesInspector methodsFor: 'accessing'!
  26594. fieldList 
  26595.     "Refer to the comment in Inspector|fieldList."
  26596.  
  26597.     object == nil ifTrue: [^Array with: 'thisContext'].
  26598.     ^(Array with: 'thisContext' with: 'all temp vars') , object tempNames! !
  26599.  
  26600. !ContextVariablesInspector methodsFor: 'accessing' stamp: 'sw 9/12/97 21:47'!
  26601. selectedSlotName
  26602.      ^ object tempNames at: (self selectionIndex - 2)! !
  26603.  
  26604.  
  26605. !ContextVariablesInspector methodsFor: 'selecting'!
  26606. replaceSelectionValue: anObject 
  26607.     "Refer to the comment in Inspector|replaceSelectionValue:."
  26608.  
  26609.     selectionIndex = 1
  26610.         ifTrue: [^object]
  26611.         ifFalse: [^object tempAt: selectionIndex - 2 put: anObject]! !
  26612.  
  26613. !ContextVariablesInspector methodsFor: 'selecting'!
  26614. selection 
  26615.     "Refer to the comment in Inspector|selection."
  26616.  
  26617.     selectionIndex = 1 ifTrue: [^object].
  26618.     selectionIndex = 2
  26619.         ifTrue: [^object tempsAndValues]
  26620.         ifFalse: [^object tempAt: selectionIndex - 2]! !
  26621.  
  26622.  
  26623. !ContextVariablesInspector methodsFor: 'code'!
  26624. doItContext
  26625.  
  26626.     ^object! !
  26627.  
  26628. !ContextVariablesInspector methodsFor: 'code'!
  26629. doItReceiver
  26630.  
  26631.     ^object receiver! !
  26632. Object subclass: #ControlManager
  26633.     instanceVariableNames: 'scheduledControllers activeController activeControllerProcess screenController newTopClicked '
  26634.     classVariableNames: 'CmdDotEnabled '
  26635.     poolDictionaries: ''
  26636.     category: 'Interface-Framework'!
  26637. !ControlManager commentStamp: 'di 5/22/1998 16:33' prior: 0!
  26638. ControlManager comment:
  26639. 'I represent the top level control over scheduling which controller of a view on the screen the user is actively using. ScheduledControllers is the global reference to an instance of me, the one attached to the Project currently being used.'!
  26640.  
  26641.  
  26642. !ControlManager methodsFor: 'initialize-release'!
  26643. initialize
  26644.     "Initialize the receiver to refer to only the background controller."
  26645.     | screenView |
  26646.     screenController _ ScreenController new.
  26647.     screenView _ FormView new.
  26648.     screenView model: (InfiniteForm with: Color gray) controller: screenController.
  26649.     screenView window: Display boundingBox.
  26650.     scheduledControllers _ OrderedCollection with: screenController! !
  26651.  
  26652. !ControlManager methodsFor: 'initialize-release'!
  26653. release 
  26654.     "Refer to the comment in Object|release."
  26655.  
  26656.     scheduledControllers == nil
  26657.         ifFalse: 
  26658.             [scheduledControllers 
  26659.                 do: [:controller | (controller isKindOf: Controller)
  26660.                                 ifTrue: [controller view release]
  26661.                                 ifFalse: [controller release]].
  26662.             scheduledControllers _ nil]! !
  26663.  
  26664.  
  26665. !ControlManager methodsFor: 'accessing'!
  26666. activeController
  26667.     "Answer the currently active controller."
  26668.  
  26669.     ^activeController! !
  26670.  
  26671. !ControlManager methodsFor: 'accessing'!
  26672. activeController: aController 
  26673.     "Set aController to be the currently active controller. Give the user 
  26674.     control in it."
  26675.  
  26676.     activeController _ aController.
  26677.     (activeController == screenController)
  26678.         ifFalse: [self promote: activeController].
  26679.     activeControllerProcess _ 
  26680.             [activeController startUp.
  26681.             self searchForActiveController] newProcess.
  26682.     activeControllerProcess priority: Processor userSchedulingPriority.
  26683.     activeControllerProcess resume! !
  26684.  
  26685. !ControlManager methodsFor: 'accessing'!
  26686. activeControllerNoTerminate: aController andProcess: aProcess
  26687.     "Set aController to be the currently active controller and aProcess to be 
  26688.     the the process that handles controller scheduling activities in the 
  26689.     system. This message differs from activeController:andProcess: in that it 
  26690.     does not send controlTerminate to the currently active controller."
  26691.  
  26692.     self inActiveControllerProcess
  26693.         ifTrue: 
  26694.             [aController~~nil
  26695.                 ifTrue: [(scheduledControllers includes: aController)
  26696.                             ifTrue: [self promote: aController]
  26697.                             ifFalse: [self error: 'Old controller not scheduled']].
  26698.             activeController _ aController.
  26699.             activeController == nil
  26700.                 ifFalse: [activeController controlInitialize].
  26701.             activeControllerProcess _ aProcess.
  26702.             activeControllerProcess resume]
  26703.         ifFalse: 
  26704.             [self error: 'New active controller process must be set from old one'] ! !
  26705.  
  26706. !ControlManager methodsFor: 'accessing'!
  26707. activeControllerProcess
  26708.     "Answer the process that is currently handling controller scheduling 
  26709.     activities in the system."
  26710.  
  26711.     ^activeControllerProcess! !
  26712.  
  26713. !ControlManager methodsFor: 'accessing'!
  26714. controllerSatisfying: aBlock
  26715.     "Return the first scheduled controller which satisfies the 1-argument boolean-valued block, or nil if none.  7/25/96 sw"
  26716.  
  26717.     scheduledControllers do:
  26718.         [:aController | (aBlock value: aController) == true ifTrue: [^ aController]].
  26719.     ^ nil! !
  26720.  
  26721. !ControlManager methodsFor: 'accessing' stamp: 'sw 9/27/96'!
  26722. controllersSatisfying: aBlock
  26723.     "Return a list of scheduled controllers satisfying aBlock.  "
  26724.  
  26725.     ^ scheduledControllers select:
  26726.         [:aController | (aBlock value: aController) == true]! !
  26727.  
  26728. !ControlManager methodsFor: 'accessing'!
  26729. controllerWhoseModelSatisfies: aBlock
  26730.     "Return the first scheduled controller whose model satisfies the 1-argument boolean-valued block, or nil if none.  5/6/96 sw"
  26731.  
  26732.     scheduledControllers do:
  26733.         [:aController | (aBlock value: aController model) == true ifTrue: [^ aController]].
  26734.     ^ nil! !
  26735.  
  26736. !ControlManager methodsFor: 'accessing'!
  26737. includes: aController
  26738.     ^ scheduledControllers includes: aController! !
  26739.  
  26740. !ControlManager methodsFor: 'accessing'!
  26741. noteNewTop
  26742.     newTopClicked _ true! !
  26743.  
  26744. !ControlManager methodsFor: 'accessing' stamp: 'sw 10/9/96'!
  26745. removeAllControllersSatisfying: aBlock
  26746.     "Unschedule and delete all controllers satisfying aBlock.  May not leave the screen exactly right sometimes. "
  26747.  
  26748.     (self controllersSatisfying:  aBlock) do:
  26749.         [:aController | aController closeAndUnschedule]! !
  26750.  
  26751. !ControlManager methodsFor: 'accessing'!
  26752. scheduledControllers
  26753.     "Answer a copy of the ordered collection of scheduled controllers."
  26754.  
  26755.     ^scheduledControllers copy! !
  26756.  
  26757. !ControlManager methodsFor: 'accessing' stamp: 'di 10/4/97 09:05'!
  26758. scheduledWindowControllers
  26759.     "Same as scheduled controllers, but without ScreenController.
  26760.     Avoids null views just after closing, eg, a debugger."
  26761.  
  26762.     ^ scheduledControllers select:
  26763.         [:c | c ~~ screenController and: [c view ~~ nil]]! !
  26764.  
  26765. !ControlManager methodsFor: 'accessing'!
  26766. screenController
  26767.     ^ screenController! !
  26768.  
  26769. !ControlManager methodsFor: 'accessing'!
  26770. windowOriginsInUse
  26771.     "Answer a collection of the origins of windows currently on the screen in the current project.  5/21/96 sw"
  26772.  
  26773.     ^ self scheduledWindowControllers collect: [:aController | aController view displayBox origin].! !
  26774.  
  26775.  
  26776. !ControlManager methodsFor: 'scheduling'!
  26777. activateController: aController
  26778.     "Make aController, which must already be a scheduled controller, the active window.  5/8/96 sw"
  26779.  
  26780.     self activeController: aController.
  26781.     (activeController view labelDisplayBox
  26782.         intersect: Display boundingBox) area < 200
  26783.             ifTrue: [activeController move].
  26784.     Processor terminateActive! !
  26785.  
  26786. !ControlManager methodsFor: 'scheduling'!
  26787. activateTranscript
  26788.     "There is known to be a Transcript open in the current project; activate it.  2/5/96 sw"
  26789.  
  26790.     | itsController |
  26791.     itsController _ scheduledControllers detect:
  26792.             [:controller | controller model == Transcript]
  26793.         ifNone:
  26794.             [^ self].
  26795.  
  26796.     self activeController: itsController.
  26797.     (activeController view labelDisplayBox
  26798.             intersect: Display boundingBox) area < 200
  26799.                 ifTrue: [activeController move].
  26800.     Processor terminateActive! !
  26801.  
  26802. !ControlManager methodsFor: 'scheduling' stamp: 'sw 9/30/97 13:26'!
  26803. cmdDotEnabled
  26804.     ^ CmdDotEnabled ~~ false! !
  26805.  
  26806. !ControlManager methodsFor: 'scheduling' stamp: 'sw 9/30/97 13:26'!
  26807. cmdDotEnabled: aBoolean
  26808.     CmdDotEnabled _ aBoolean! !
  26809.  
  26810. !ControlManager methodsFor: 'scheduling' stamp: 'di 5/19/1998 09:03'!
  26811. findWindow
  26812.     "Present a menu of window titles, and activate the one that gets chosen."
  26813.  
  26814.     ^ self findWindowSatisfying: [:c | true]! !
  26815.  
  26816. !ControlManager methodsFor: 'scheduling' stamp: 'sw 10/12/97 21:48'!
  26817. findWindowSatisfying: aBlock
  26818.     "Present a menu of window titles, and activate the one that gets chosen"
  26819.  
  26820.     | controllers labels index listToUse sortAlphabetically |
  26821.     sortAlphabetically _ Sensor optionKeyPressed.
  26822.     controllers _ OrderedCollection new.
  26823.     scheduledControllers do:
  26824.         [:controller | controller == screenController ifFalse:
  26825.             [(aBlock value: controller) ifTrue: [controllers addLast: controller]]].
  26826.     controllers size == 0 ifTrue: [^ self].
  26827.     listToUse _ sortAlphabetically
  26828.         ifTrue:
  26829.             [controllers asSortedCollection: [:a :b | a view label < b view label]]
  26830.         ifFalse:
  26831.             [controllers].
  26832.     labels _ String streamContents:
  26833.         [:strm | 
  26834.             listToUse do: [:controller | strm nextPutAll: (controller view label contractTo: 40); cr].
  26835.         strm skip: -1  "drop last cr"].
  26836.     index _ (PopUpMenu labels: labels) startUp.
  26837.     index > 0 ifTrue:
  26838.         [self activateController: (controllers at: index)]! !
  26839.  
  26840. !ControlManager methodsFor: 'scheduling'!
  26841. inActiveControllerProcess
  26842.     "Answer whether the active scheduling process is the actual active 
  26843.     process in the system."
  26844.  
  26845.     ^activeControllerProcess == Processor activeProcess! !
  26846.  
  26847. !ControlManager methodsFor: 'scheduling' stamp: 'tk 4/16/1998 15:38'!
  26848. interruptName: labelString
  26849.     "Create a Notifier on the active scheduling process with the given label. Make the Notifier the active controller."
  26850.  
  26851.     | suspendingList newActiveController |
  26852.     suspendingList _ activeControllerProcess suspendingList.
  26853.     suspendingList isNil ifTrue: [
  26854.         activeControllerProcess == Processor activeProcess
  26855.             ifTrue: [activeControllerProcess suspend].
  26856.     ] ifFalse: [
  26857.         suspendingList remove: activeControllerProcess.
  26858.         activeControllerProcess offList].
  26859.  
  26860.     activeController ~~ nil ifTrue: [
  26861.         "Carefully de-emphasis the current window."
  26862.         activeController view topView deEmphasizeForDebugger].
  26863.  
  26864.     newActiveController _
  26865.         (Debugger
  26866.             openInterrupt: labelString
  26867.             onProcess: activeControllerProcess) controller.
  26868.     newActiveController centerCursorInView.
  26869.     self activeController: newActiveController.
  26870. ! !
  26871.  
  26872. !ControlManager methodsFor: 'scheduling' stamp: 'sw 9/30/97 13:27'!
  26873. maybeForkInterrupt
  26874.  
  26875.     self cmdDotEnabled ifTrue:
  26876.         [[self interruptName: 'User Interrupt'] fork]! !
  26877.  
  26878. !ControlManager methodsFor: 'scheduling'!
  26879. promote: aController
  26880.     "Make aController be the first scheduled controller in the ordered 
  26881.     collection."
  26882.     
  26883.     scheduledControllers remove: aController.
  26884.     scheduledControllers addFirst: aController! !
  26885.  
  26886. !ControlManager methodsFor: 'scheduling'!
  26887. scheduleActive: aController 
  26888.     "Make aController be scheduled as the active controller. Presumably the 
  26889.     active scheduling process asked to schedule this controller and that a 
  26890.     new process associated this controller takes control. So this is the last act 
  26891.     of the active scheduling process."
  26892.  
  26893.     self scheduleActiveNoTerminate: aController.
  26894.     Processor terminateActive! !
  26895.  
  26896. !ControlManager methodsFor: 'scheduling'!
  26897. scheduleActiveNoTerminate: aController 
  26898.     "Make aController be the active controller. Presumably the process that 
  26899.     requested the new active controller wants to keep control to do more 
  26900.     activites before the new controller can take control. Therefore, do not 
  26901.     terminate the currently active process."
  26902.  
  26903.     self schedulePassive: aController.
  26904.     self scheduled: aController
  26905.         from: Processor activeProcess! !
  26906.  
  26907. !ControlManager methodsFor: 'scheduling'!
  26908. scheduleOnBottom: aController 
  26909.     "Make aController be scheduled as a scheduled controller, but not the 
  26910.     active one. Put it at the end of the ordered collection of controllers."
  26911.  
  26912.     scheduledControllers addLast: aController! !
  26913.  
  26914. !ControlManager methodsFor: 'scheduling'!
  26915. schedulePassive: aController 
  26916.     "Make aController be scheduled as a scheduled controller, but not the 
  26917.     active one. Put it at the beginning of the ordered collection of 
  26918.     controllers."
  26919.  
  26920.     scheduledControllers addFirst: aController! !
  26921.  
  26922. !ControlManager methodsFor: 'scheduling'!
  26923. searchForActiveController
  26924.     "Find a scheduled controller that wants control and give control to it. If 
  26925.     none wants control, then see if the System Menu has been requested."
  26926.     | aController |
  26927.     activeController _ nil.
  26928.     activeControllerProcess _ Processor activeProcess.
  26929.     self activeController: self nextActiveController.
  26930.     Processor terminateActive! !
  26931.  
  26932. !ControlManager methodsFor: 'scheduling'!
  26933. unschedule: aController
  26934.     "Remove the view, aController, from the collection of scheduled 
  26935.     controllers."
  26936.  
  26937.     scheduledControllers remove: aController ifAbsent: []! !
  26938.  
  26939. !ControlManager methodsFor: 'scheduling'!
  26940. windowFromUser
  26941.     "Present a menu of window titles, and returns the StandardSystemController belonging to the one that gets chosen, or nil if none"
  26942.     | controllers labels index |
  26943.     controllers _ OrderedCollection new.
  26944.     labels _ String streamContents:
  26945.         [:strm |
  26946.         scheduledControllers do:
  26947.             [:controller | controller == screenController ifFalse:
  26948.                 [controllers addLast: controller.
  26949.                 strm nextPutAll: (controller view label contractTo: 40); cr]].
  26950.         strm skip: -1  "drop last cr"].
  26951.     index _ (PopUpMenu labels: labels) startUp.
  26952.     ^ index > 0
  26953.         ifTrue:
  26954.             [controllers at: index]
  26955.         ifFalse:
  26956.             [nil]! !
  26957.  
  26958.  
  26959. !ControlManager methodsFor: 'displaying'!
  26960. backgroundForm: aForm
  26961.     screenController view model: aForm.
  26962.     ScheduledControllers restore
  26963. "
  26964.     QDPen new mandala: 30 diameter: 640.
  26965.     ScheduledControllers backgroundForm:
  26966.         (Form fromDisplay: Display boundingBox).
  26967.  
  26968.     ScheduledControllers backgroundForm:
  26969.         (InfiniteForm with: Form gray).
  26970. "! !
  26971.  
  26972. !ControlManager methodsFor: 'displaying' stamp: 'di 2/26/98 08:58'!
  26973. restore 
  26974.     "Clear the screen to gray and then redisplay all the scheduled views.  Try to be a bit intelligent about the view that wants control and not display it twice if possible."
  26975.  
  26976.     scheduledControllers first view uncacheBits.  "assure refresh"
  26977.     self unschedule: screenController; scheduleOnBottom: screenController.
  26978.     screenController view window: Display boundingBox; displayDeEmphasized.
  26979.     self scheduledWindowControllers reverseDo:
  26980.         [:aController | aController view displayDeEmphasized].
  26981. ! !
  26982.  
  26983. !ControlManager methodsFor: 'displaying'!
  26984. restore: aRectangle
  26985.     "Restore all windows visible in aRectangle"
  26986.     ^ self restore: aRectangle below: 1 without: nil! !
  26987.  
  26988. !ControlManager methodsFor: 'displaying'!
  26989. restore: aRectangle below: index without: aView
  26990.     "Restore all windows visible in aRectangle, but without aView"
  26991.     | view | 
  26992.     view _ (scheduledControllers at: index) view.
  26993.     view == aView ifTrue: 
  26994.         [index >= scheduledControllers size ifTrue: [^ self].
  26995.         ^ self restore: aRectangle below: index+1 without: aView].
  26996.     view displayOn: ((BitBlt toForm: Display) clipRect: aRectangle).
  26997.     index >= scheduledControllers size ifTrue: [^ self].
  26998.     (aRectangle areasOutside: view windowBox) do:
  26999.         [:rect | self restore: rect below: index + 1 without: aView]! !
  27000.  
  27001. !ControlManager methodsFor: 'displaying'!
  27002. restore: aRectangle without: aView
  27003.     "Restore all windows visible in aRectangle"
  27004.     ^ self restore: aRectangle below: 1 without: aView! !
  27005.  
  27006. !ControlManager methodsFor: 'displaying'!
  27007. updateGray
  27008.     "From Georg Gollmann - 11/96.  tell the Screen Controller's model to use the currently-preferred desktop color."
  27009.  
  27010.     "ScheduledControllers updateGray"
  27011.     (screenController view model isMemberOf: InfiniteForm)
  27012.         ifTrue: [screenController view model: (InfiniteForm with:
  27013. Preferences desktopColor)]! !
  27014.  
  27015.  
  27016. !ControlManager methodsFor: 'private'!
  27017. nextActiveController
  27018.     "Answer the controller that would like control.  
  27019.     If there was a click outside the active window, it's the top window
  27020.     that now has the mouse, otherwise it's just the top window."
  27021.  
  27022.     (newTopClicked notNil and: [newTopClicked])
  27023.         ifTrue: [newTopClicked _ false.
  27024.                 ^ scheduledControllers 
  27025.                     detect: [:aController | aController isControlWanted]
  27026.                     ifNone: [scheduledControllers first]]
  27027.         ifFalse: [^ scheduledControllers first]! !
  27028.  
  27029. !ControlManager methodsFor: 'private'!
  27030. scheduled: aController from: aProcess
  27031.  
  27032.     activeControllerProcess==aProcess
  27033.         ifTrue: 
  27034.             [activeController ~~ nil
  27035.                     ifTrue: [activeController controlTerminate].
  27036.             aController centerCursorInView.
  27037.             self activeController: aController]! !
  27038.  
  27039. !ControlManager methodsFor: 'private'!
  27040. unCacheWindows
  27041.     scheduledControllers do:
  27042.         [:aController | aController view uncacheBits]! !
  27043.  
  27044. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27045.  
  27046. ControlManager class
  27047.     instanceVariableNames: ''!
  27048.  
  27049. !ControlManager class methodsFor: 'instance creation' stamp: 'sw 9/30/97 13:25'!
  27050. initialize
  27051.     "ControlManager initialize"
  27052.     CmdDotEnabled _ true! !
  27053.  
  27054. !ControlManager class methodsFor: 'instance creation'!
  27055. new
  27056.     ^super new initialize! !
  27057.  
  27058.  
  27059. !ControlManager class methodsFor: 'exchange'!
  27060. newScheduler: controlManager
  27061.     "When switching projects, the control scheduler has to be exchanged. The 
  27062.     active one is the one associated with the current project."
  27063.  
  27064.     Smalltalk at: #ScheduledControllers put: controlManager.
  27065.     ScheduledControllers restore.
  27066.     controlManager searchForActiveController! !
  27067.  
  27068.  
  27069. !ControlManager class methodsFor: 'snapshots' stamp: 'di 6/16/97 11:42'!
  27070. shutDown  "Saves space in snapshots"
  27071.     ScheduledControllers unCacheWindows! !
  27072.  
  27073. !ControlManager class methodsFor: 'snapshots'!
  27074. startUp
  27075.     ScheduledControllers restore! !
  27076. Object subclass: #Controller
  27077.     instanceVariableNames: 'model view sensor '
  27078.     classVariableNames: ''
  27079.     poolDictionaries: ''
  27080.     category: 'Interface-Framework'!
  27081. !Controller commentStamp: 'di 5/22/1998 16:33' prior: 0!
  27082. Controller comment:
  27083. 'A Controller coordinates a View, its model, and user actions. It provides scheduling (control) behavior to determine when the user wants to communicate with the model or view.'!
  27084.  
  27085.  
  27086. !Controller methodsFor: 'initialize-release'!
  27087. initialize
  27088.     "Initialize the state of the receiver. Subclasses should include 'super 
  27089.     initialize' when redefining this message to insure proper initialization."
  27090.  
  27091.     sensor _ InputSensor default! !
  27092.  
  27093. !Controller methodsFor: 'initialize-release'!
  27094. release
  27095.     "Breaks the cycle between the receiver and its view. It is usually not 
  27096.     necessary to send release provided the receiver's view has been properly 
  27097.     released independently."
  27098.  
  27099.     model _ nil.
  27100.     view ~~ nil
  27101.         ifTrue: 
  27102.             [view controller: nil.
  27103.             view _ nil]! !
  27104.  
  27105.  
  27106. !Controller methodsFor: 'model access'!
  27107. model
  27108.     "Answer the receiver's model which is the same as the model of the 
  27109.     receiver's view."
  27110.  
  27111.     ^model! !
  27112.  
  27113. !Controller methodsFor: 'model access'!
  27114. model: aModel 
  27115.     "Controller|model: and Controller|view: are sent by View|controller: in 
  27116.     order to coordinate the links between the model, view, and controller. In 
  27117.     ordinary usage, the receiver is created and passed as the parameter to 
  27118.     View|controller: so that the receiver's model and view links can be set 
  27119.     up by the view."
  27120.  
  27121.     model _ aModel! !
  27122.  
  27123.  
  27124. !Controller methodsFor: 'view access'!
  27125. inspectView
  27126.     view notNil ifTrue: [^ view inspect]! !
  27127.  
  27128. !Controller methodsFor: 'view access'!
  27129. view
  27130.     "Answer the receiver's view."
  27131.  
  27132.     ^view! !
  27133.  
  27134. !Controller methodsFor: 'view access'!
  27135. view: aView 
  27136.     "Controller|view: and Controller|model: are sent by View|controller: in 
  27137.     order to coordinate the links between the model, view, and controller. In 
  27138.     ordinary usage, the receiver is created and passed as the parameter to 
  27139.     View|controller: and the receiver's model and view links are set up 
  27140.     automatically by the view."
  27141.  
  27142.     view _ aView! !
  27143.  
  27144.  
  27145. !Controller methodsFor: 'sensor access'!
  27146. sensor
  27147.     "Answer the receiver's sensor. Subclasses may use other objects that are 
  27148.     not instances of Sensor or its subclasses if more general kinds of 
  27149.     input/output functions are required."
  27150.  
  27151.     ^sensor! !
  27152.  
  27153. !Controller methodsFor: 'sensor access'!
  27154. sensor: aSensor
  27155.     "Set the receiver's sensor to aSensor."
  27156.  
  27157.     sensor _ aSensor! !
  27158.  
  27159.  
  27160. !Controller methodsFor: 'basic control sequence'!
  27161. controlInitialize
  27162.     "Sent by Controller|startUp as part of the standard control sequence, it 
  27163.     provides a place in the standard control sequence for initializing the 
  27164.     receiver (taking into account the current state of its model and view). It 
  27165.     should be redefined in subclasses to perform some specific action."
  27166.  
  27167.     ^self! !
  27168.  
  27169. !Controller methodsFor: 'basic control sequence'!
  27170. controlLoop 
  27171.     "Sent by Controller|startUp as part of the standard control sequence. 
  27172.     Controller|controlLoop sends the message Controller|isControlActive to test 
  27173.     for loop termination. As long as true is returned, the loop continues. 
  27174.     When false is returned, the loop ends. Each time through the loop, the 
  27175.     message Controller|controlActivity is sent."
  27176.  
  27177.     [self isControlActive] whileTrue: [self controlActivity. Processor yield]! !
  27178.  
  27179. !Controller methodsFor: 'basic control sequence'!
  27180. controlTerminate
  27181.     "Provide a place in the standard control sequence for terminating the 
  27182.     receiver (taking into account the current state of its model and view). It 
  27183.     should be redefined in subclasses to perform some specific action."
  27184.  
  27185.     ^self! !
  27186.  
  27187. !Controller methodsFor: 'basic control sequence'!
  27188. startUp
  27189.     "Give control to the receiver. The default control sequence is to initialize 
  27190.     (see Controller|controlInitialize), to loop (see Controller|controlLoop), and 
  27191.     then to terminate (see Controller|controlTerminate). After this sequence, 
  27192.     control is returned to the sender of Control|startUp. The receiver's control 
  27193.     sequence is used to coordinate the interaction of its view and model. In 
  27194.     general, this consists of polling the sensor for user input, testing the 
  27195.     input with respect to the current display of the view, and updating the 
  27196.     model to reflect intended changes."
  27197.  
  27198.     self controlInitialize.
  27199.     self controlLoop.
  27200.     self controlTerminate! !
  27201.  
  27202. !Controller methodsFor: 'basic control sequence'!
  27203. terminateAndInitializeAround: aBlock
  27204.     "1/12/96 sw"
  27205.     self controlTerminate.
  27206.     aBlock value.
  27207.     self controlInitialize! !
  27208.  
  27209.  
  27210. !Controller methodsFor: 'control defaults'!
  27211. controlActivity
  27212.     "Pass control to the next control level (that is, to the Controller of a 
  27213.     subView of the receiver's view) if possible. It is sent by 
  27214.     Controller|controlLoop each time through the main control loop. It should 
  27215.     be redefined in a subclass if some other action is needed."
  27216.  
  27217.     self controlToNextLevel! !
  27218.  
  27219. !Controller methodsFor: 'control defaults'!
  27220. controlToNextLevel
  27221.     "Pass control to the next control level (that is, to the Controller of a 
  27222.     subView of the receiver's view) if possible. The receiver finds the 
  27223.     subView (if any) of its view whose inset display box (see 
  27224.     View|insetDisplayBox) contains the sensor's cursor point. The Controller 
  27225.     of this subView is then given control if it answers true in response to 
  27226.     the message Controller|isControlWanted."
  27227.  
  27228.     | aView |
  27229.     aView _ view subViewWantingControl.
  27230.     aView ~~ nil ifTrue: [aView controller startUp]! !
  27231.  
  27232. !Controller methodsFor: 'control defaults'!
  27233. isControlActive
  27234.     "Answer whether receiver wishes to continue evaluating its controlLoop 
  27235.     method. It is sent by Controller|controlLoop in order to determine when 
  27236.     the receiver's control loop should terminate, and should be redefined in 
  27237.     a subclass if some special condition for terminating the main control loop 
  27238.     is needed."
  27239.  
  27240.     ^ self viewHasCursor
  27241.         & sensor blueButtonPressed not
  27242.         & sensor yellowButtonPressed not
  27243.         "& sensor cmdKeyPressed not"! !
  27244.  
  27245. !Controller methodsFor: 'control defaults'!
  27246. isControlWanted
  27247.     "Answer whether the cursor is inside the inset display box (see 
  27248.     View|insetDisplayBox) of the receiver's view. It is sent by 
  27249.     Controller|controlNextLevel in order to determine whether or not control 
  27250.     should be passed to this receiver from the Controller of the superView of 
  27251.     this receiver's view."
  27252.  
  27253.     ^self viewHasCursor! !
  27254.  
  27255.  
  27256. !Controller methodsFor: 'cursor'!
  27257. centerCursorInView
  27258.     "Position sensor's mousePoint (which is assumed to be connected to the 
  27259.     cursor) to the center of its view's inset display box (see 
  27260.     Sensor|mousePoint: and View|insetDisplayBox)."
  27261.  
  27262.     ^sensor cursorPoint: view insetDisplayBox center! !
  27263.  
  27264. !Controller methodsFor: 'cursor'!
  27265. viewHasCursor
  27266.     "Answer whether the cursor point of the receiver's sensor lies within the 
  27267.     inset display box of the receiver's view (see View|insetDisplayBox). 
  27268.     Controller|viewHasCursor is normally used in internal methods."
  27269.  
  27270.     ^view containsPoint: sensor cursorPoint! !
  27271.  
  27272. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27273.  
  27274. Controller class
  27275.     instanceVariableNames: ''!
  27276.  
  27277. !Controller class methodsFor: 'instance creation'!
  27278. new
  27279.  
  27280.     ^super new initialize! !
  27281. Form subclass: #Cursor
  27282.     instanceVariableNames: ''
  27283.     classVariableNames: 'BlankCursor CornerCursor CrossHairCursor CurrentCursor DownCursor MarkerCursor MenuCursor MoveCursor NormalCursor OriginCursor ReadCursor RightArrowCursor SquareCursor UpCursor WaitCursor WriteCursor XeqCursor '
  27284.     poolDictionaries: ''
  27285.     category: 'Graphics-Display Objects'!
  27286. !Cursor commentStamp: 'di 5/22/1998 16:33' prior: 0!
  27287. Cursor comment:
  27288. 'I am a 16 x 16 dot matrix suitable for use as the Alto hardware cursor.'!
  27289.  
  27290.  
  27291. !Cursor methodsFor: 'updating'!
  27292. changed: aParameter
  27293.  
  27294.     self == CurrentCursor ifTrue: [self beCursor].
  27295.     super changed: aParameter! !
  27296.  
  27297.  
  27298. !Cursor methodsFor: 'displaying'!
  27299. beCursor
  27300.     "Primitive. Tell the interpreter to use the receiver as the current cursor 
  27301.     image. Fail if the receiver does not match the size expected by the 
  27302.     hardware. Essential. See Object documentation whatIsAPrimitive."
  27303.  
  27304.     <primitive: 101>
  27305.     self primitiveFailed! !
  27306.  
  27307. !Cursor methodsFor: 'displaying'!
  27308. show
  27309.     "Make the current cursor shape be the receiver."
  27310.  
  27311.     Sensor currentCursor: self! !
  27312.  
  27313. !Cursor methodsFor: 'displaying'!
  27314. showGridded: gridPoint 
  27315.     "Make the current cursor shape be the receiver, forcing the location of the cursor to the point nearest gridPoint."
  27316.     
  27317.     Sensor cursorPoint: (Sensor cursorPoint grid: gridPoint).
  27318.     Sensor currentCursor: self! !
  27319.  
  27320. !Cursor methodsFor: 'displaying'!
  27321. showWhile: aBlock 
  27322.     "While evaluating the argument, aBlock, make the receiver be the cursor 
  27323.     shape."
  27324.  
  27325.     | oldcursor value |
  27326.     oldcursor _ Sensor currentCursor.
  27327.     self show.
  27328.     value _ aBlock value.
  27329.     oldcursor show.
  27330.     ^value! !
  27331.  
  27332.  
  27333. !Cursor methodsFor: 'printing'!
  27334. printOn: aStream
  27335.  
  27336.     self storeOn: aStream base: 2! !
  27337.  
  27338. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  27339.  
  27340. Cursor class
  27341.     instanceVariableNames: ''!
  27342.  
  27343. !Cursor class methodsFor: 'class initialization'!
  27344. initCorner
  27345.  
  27346.     CornerCursor _ 
  27347.         (Cursor 
  27348.             extent: 16@16
  27349.             fromArray: #(
  27350.         2r0000000000000011
  27351.         2r0000000000000011
  27352.         2r0000000000000011
  27353.         2r0000000000000011
  27354.         2r0000000000000011
  27355.         2r0000000000000011
  27356.         2r0000000000000011
  27357.         2r0000000000000011
  27358.         2r0000000000000011
  27359.         2r0000000000000011
  27360.         2r0000000000000011
  27361.         2r0000000000000011
  27362.         2r0000000000000011
  27363.         2r0000000000000011
  27364.         2r1111111111111111
  27365.         2r1111111111111111)
  27366.             offset: -16@-16).
  27367. ! !
  27368.  
  27369. !Cursor class methodsFor: 'class initialization'!
  27370. initCrossHair
  27371.  
  27372.     CrossHairCursor _   
  27373.         (Cursor
  27374.             extent: 16@16
  27375.             fromArray: #(
  27376.         2r0000000100000000
  27377.         2r0000000100000000
  27378.         2r0000000100000000
  27379.         2r0000000100000000
  27380.         2r0000000100000000
  27381.         2r0000000100000000
  27382.         2r0000000100000000
  27383.         2r1111111111111110
  27384.         2r0000000100000000
  27385.         2r0000000100000000
  27386.         2r0000000100000000
  27387.         2r0000000100000000
  27388.         2r0000000100000000
  27389.         2r0000000100000000
  27390.         2r0000000100000000
  27391.         2r0)
  27392.             offset: -7@-7).
  27393.     
  27394.     ! !
  27395.  
  27396. !Cursor class methodsFor: 'class initialization'!
  27397. initDown
  27398.  
  27399.     DownCursor  _
  27400.              (Cursor
  27401.     extent: 16@16
  27402.     fromArray: #(
  27403.         2r11000000000000
  27404.         2r11000000000000
  27405.         2r11000000000000
  27406.         2r11000000000000
  27407.         2r11000000000000
  27408.         2r11000000000000
  27409.         2r11000000000000
  27410.         2r1111110000000000
  27411.         2r111100000000000
  27412.         2r11000000000000
  27413.         2r0
  27414.         2r0
  27415.         2r0
  27416.         2r0
  27417.         2r0
  27418.         2r0)
  27419.     offset: 0@0).
  27420. ! !
  27421.  
  27422. !Cursor class methodsFor: 'class initialization'!
  27423. initialize
  27424.     "Create all the standard cursors
  27425.         Cursor origin
  27426.         Cursor rightArrow
  27427.         Cursor menu
  27428.         Cursor corner
  27429.         Cursor read
  27430.         Cursor write
  27431.         Cursor wait
  27432.         Cursor blank
  27433.         Cursor xeq
  27434.         Cursor square
  27435.         Cursor normal
  27436.         Cursor crossHair
  27437.         Cursor marker
  27438.         Cursor up
  27439.         Cursor down
  27440.         Cursor move"
  27441.  
  27442.         self initOrigin.
  27443.         self initRightArrow.
  27444.         self initMenu.
  27445.         self initCorner.
  27446.         self initRead.
  27447.         self initWrite.
  27448.         self initWait.
  27449.         BlankCursor _ Cursor new.
  27450.         self initXeq.
  27451.         self initSquare.
  27452.         self initNormal.
  27453.         self initCrossHair.
  27454.         self initMarker.
  27455.         self initUp.
  27456.         self initDown.
  27457.         self initMove.
  27458.  
  27459.         "Cursor initialize"
  27460. ! !
  27461.  
  27462. !Cursor class methodsFor: 'class initialization'!
  27463. initMarker
  27464.  
  27465.     MarkerCursor _ 
  27466.         Cursor
  27467.             extent: 16@16
  27468.             fromArray: #(
  27469.         2r0111000000000000
  27470.         2r1111100000000000
  27471.         2r1111100000000000
  27472.         2r0111000000000000
  27473.         2r0
  27474.         2r0
  27475.         2r0
  27476.         2r0
  27477.         2r0
  27478.         2r0
  27479.         2r0
  27480.         2r0
  27481.         2r0
  27482.         2r0
  27483.         2r0
  27484.         2r0)
  27485.             offset: 0@0.
  27486. ! !
  27487.  
  27488. !Cursor class methodsFor: 'class initialization'!
  27489. initMenu 
  27490.  
  27491.     MenuCursor  _
  27492.                 (Cursor
  27493.     extent: 16@16
  27494.     fromArray: #(
  27495.         2r1111111111100000
  27496.         2r1000000000100000
  27497.         2r1010011000100000
  27498.         2r1000000000100000
  27499.         2r1011001010100000
  27500.         2r1000000000100000
  27501.         2r1010110010100000
  27502.         2r1000000000100000
  27503.         2r1010010100100000
  27504.         2r1000000000100000
  27505.         2r1111111111100000
  27506.         2r1101001101100000
  27507.         2r1111111111100000
  27508.         2r1000000000100000
  27509.         2r1010101100100000
  27510.         2r1111111111100000)
  27511.     offset: 0@0).
  27512. ! !
  27513.  
  27514. !Cursor class methodsFor: 'class initialization'!
  27515. initMove
  27516.  
  27517.     MoveCursor _ 
  27518.         Cursor 
  27519.             extent: 16@16
  27520.             fromArray: #(
  27521.         2r1111111111111111
  27522.         2r1111111111111111
  27523.         2r1100000110000011
  27524.         2r1100000110000011
  27525.         2r1100000110000011
  27526.         2r1100000110000011
  27527.         2r1100000110000011
  27528.         2r1111111111111111
  27529.         2r1111111111111111
  27530.         2r1100000110000011
  27531.         2r1100000110000011
  27532.         2r1100000110000011
  27533.         2r1100000110000011
  27534.         2r1100000110000011
  27535.         2r1111111111111111
  27536.         2r1111111111111111)
  27537.             offset: 0@0.
  27538. ! !
  27539.  
  27540. !Cursor class methodsFor: 'class initialization'!
  27541. initNormal
  27542.  
  27543.     NormalCursor _   
  27544.         (Cursor
  27545.             extent: 16@16
  27546.             fromArray: #(
  27547.         2r1000000000000000
  27548.         2r1100000000000000
  27549.         2r1110000000000000
  27550.         2r1111000000000000
  27551.         2r1111100000000000
  27552.         2r1111110000000000
  27553.         2r1111111000000000
  27554.         2r1111100000000000
  27555.         2r1111100000000000
  27556.         2r1001100000000000
  27557.         2r0000110000000000
  27558.         2r0000110000000000
  27559.         2r0000011000000000
  27560.         2r0000011000000000
  27561.         2r0000001100000000
  27562.         2r0000001100000000)
  27563.     offset: 0@0).
  27564.  
  27565.     
  27566.     ! !
  27567.  
  27568. !Cursor class methodsFor: 'class initialization'!
  27569. initOrigin
  27570.  
  27571.     OriginCursor _   
  27572.         (Cursor
  27573.             extent: 16@16
  27574.             fromArray: #(
  27575.         2r1111111111111111
  27576.         2r1111111111111111
  27577.         2r1100000000000000
  27578.         2r1100000000000000
  27579.         2r1100000000000000
  27580.         2r1100000000000000
  27581.         2r1100000000000000
  27582.         2r1100000000000000
  27583.         2r1100000000000000
  27584.         2r1100000000000000
  27585.         2r1100000000000000
  27586.         2r1100000000000000
  27587.         2r1100000000000000
  27588.         2r1100000000000000
  27589.         2r1100000000000000
  27590.         2r1100000000000000)
  27591.             offset: 0@0).
  27592. ! !
  27593.  
  27594. !Cursor class methodsFor: 'class initialization'!
  27595. initRead
  27596.  
  27597.     ReadCursor _  
  27598.         (Cursor
  27599.             extent: 16@16
  27600.             fromArray: #(
  27601.         2r0000110000000110
  27602.         2r0001001000001001
  27603.         2r0001001000001001
  27604.         2r0010000000010000
  27605.         2r0100000000100000
  27606.         2r1111101111100000
  27607.         2r1000010000100000
  27608.         2r1000010000100000
  27609.         2r1011010110100000
  27610.         2r0111101111000000
  27611.         2r0
  27612.         2r0
  27613.         2r0
  27614.         2r0
  27615.         2r0
  27616.         2r0)
  27617.     offset: 0@0).
  27618. ! !
  27619.  
  27620. !Cursor class methodsFor: 'class initialization'!
  27621. initRightArrow 
  27622.  
  27623.     RightArrowCursor  _
  27624.               (Cursor
  27625.     extent: 16@16
  27626.     fromArray: #(
  27627.         2r100000000000
  27628.         2r111000000000
  27629.         2r1111111110000000
  27630.         2r111000000000
  27631.         2r100000000000
  27632.         2r0
  27633.         2r0
  27634.         2r0
  27635.         2r0
  27636.         2r0
  27637.         2r0
  27638.         2r0
  27639.         2r0
  27640.         2r0
  27641.         2r0
  27642.         2r0)
  27643.     offset: 0@0).
  27644.     
  27645.     "Cursor initRightArrow"! !
  27646.  
  27647. !Cursor class methodsFor: 'class initialization'!
  27648. initSquare
  27649.  
  27650.     SquareCursor _ 
  27651.         (Cursor
  27652.             extent: 16@16
  27653.             fromArray: #(
  27654.         2r0
  27655.         2r0
  27656.         2r0
  27657.         2r0
  27658.         2r0
  27659.         2r0000001111000000
  27660.         2r0000001111000000
  27661.         2r0000001111000000
  27662.         2r0000001111000000
  27663.         2r0
  27664.         2r0
  27665.         2r0
  27666.         2r0
  27667.         2r0
  27668.         2r0
  27669.         2r0)
  27670.     offset: -8@-8).
  27671.  
  27672.     ! !
  27673.  
  27674. !Cursor class methodsFor: 'class initialization'!
  27675. initUp
  27676.  
  27677.     UpCursor _ 
  27678.             (Cursor
  27679.     extent: 16@16
  27680.     fromArray: #(
  27681.         2r11000000000000
  27682.         2r111100000000000
  27683.         2r1111110000000000
  27684.         2r11000000000000
  27685.         2r11000000000000
  27686.         2r11000000000000
  27687.         2r11000000000000
  27688.         2r11000000000000
  27689.         2r11000000000000
  27690.         2r11000000000000
  27691.         2r0
  27692.         2r0
  27693.         2r0
  27694.         2r0
  27695.         2r0
  27696.         2r0)
  27697.     offset: 0@0).
  27698. ! !
  27699.  
  27700. !Cursor class methodsFor: 'class initialization'!
  27701. initWait
  27702.  
  27703.     WaitCursor _ 
  27704.           (Cursor
  27705.             extent: 16@16
  27706.             fromArray: #(
  27707.         2r1111111111111111
  27708.         2r1000000000000001
  27709.         2r0100000000000010
  27710.         2r0010000000000100
  27711.         2r0001110000111000
  27712.         2r0000111101110000
  27713.         2r0000011011100000
  27714.         2r0000001111000000
  27715.         2r0000001111000000
  27716.         2r0000010110100000
  27717.         2r0000100010010000
  27718.         2r0001000110001000
  27719.         2r0010001101000100
  27720.         2r0100111111110010
  27721.         2r1011111111111101
  27722.         2r1111111111111111)
  27723.             offset: 0@0).
  27724. ! !
  27725.  
  27726. !Cursor class methodsFor: 'class initialization'!
  27727. initWrite
  27728.  
  27729.     WriteCursor _ (Cursor
  27730.     extent: 16@16
  27731.     fromArray: #(
  27732.         2r0000000000000110
  27733.         2r0000000000001111
  27734.         2r0000000000010110
  27735.         2r0000000000100100
  27736.         2r0000000001001000
  27737.         2r0000000010010000
  27738.         2r0000000100100000
  27739.         2r0000001001000011
  27740.         2r0000010010000010
  27741.         2r0000100100000110
  27742.         2r0001001000001000
  27743.         2r0010010000001000
  27744.         2r0111100001001000
  27745.         2r0101000010111000
  27746.         2r0110000110000000
  27747.         2r1111111100000000)
  27748.     offset: 0@0).
  27749. ! !
  27750.  
  27751. !Cursor class methodsFor: 'class initialization'!
  27752. initXeq
  27753.  
  27754.     XeqCursor _ 
  27755.         (Cursor
  27756.             extent: 16@16
  27757.             fromArray: #(
  27758.         2r1000000000010000
  27759.         2r1100000000010000
  27760.         2r1110000000111000
  27761.         2r1111000111111111
  27762.         2r1111100011000110
  27763.         2r1111110001000100
  27764.         2r1111111001111100
  27765.         2r1111000001101100
  27766.         2r1101100011000110
  27767.         2r1001100010000010
  27768.         2r0000110000000000
  27769.         2r0000110000000000
  27770.         2r0000011000000000
  27771.         2r0000011000000000
  27772.         2r0000001100000000
  27773.         2r0000001100000000)
  27774.     offset: 0@0).
  27775. ! !
  27776.  
  27777. !Cursor class methodsFor: 'class initialization'!
  27778. startUp
  27779.     self currentCursor: self currentCursor! !
  27780.  
  27781.  
  27782. !Cursor class methodsFor: 'instance creation'!
  27783. extent: extentPoint fromArray: anArray offset: offsetPoint 
  27784.     "Answer a new instance of me with width and height specified by
  27785.     extentPoint, offset by offsetPoint, and bits from anArray.
  27786.     NOTE: This has been kluged to take an array of 16-bit constants,
  27787.     and shift them over so they are left-justified in a 32-bit bitmap"
  27788.  
  27789.     extentPoint = (16 @ 16)
  27790.         ifTrue: 
  27791.             [^ super
  27792.                 extent: extentPoint
  27793.                 fromArray: (anArray collect: [:bits | bits bitShift: 16])
  27794.                 offset: offsetPoint]
  27795.         ifFalse: [self error: 'cursors must be 16@16']! !
  27796.  
  27797. !Cursor class methodsFor: 'instance creation'!
  27798. new
  27799.  
  27800.     ^self
  27801.         extent: 16 @ 16
  27802.         fromArray: Array new
  27803.         offset: 0 @ 0
  27804.  
  27805.     "Cursor new bitEdit show"! !
  27806.  
  27807.  
  27808. !Cursor class methodsFor: 'current cursor'!
  27809. currentCursor
  27810.     "Answer the instance of Cursor that is the one currently displayed."
  27811.  
  27812.     ^CurrentCursor! !
  27813.  
  27814. !Cursor class methodsFor: 'current cursor'!
  27815. currentCursor: aCursor 
  27816.     "Make the instance of cursor, aCursor, be the current cursor. Display it. 
  27817.     Create an error if the argument is not a Cursor."
  27818.  
  27819.     aCursor class == self
  27820.         ifTrue: 
  27821.             [CurrentCursor _ aCursor.
  27822.             aCursor beCursor]
  27823.         ifFalse: [self error: 'The new cursor must be an instance of class Cursor']! !
  27824.  
  27825.  
  27826. !Cursor class methodsFor: 'constants'!
  27827. blank
  27828.     "Answer the instance of me that is all white."
  27829.  
  27830.     ^BlankCursor! !
  27831.  
  27832. !Cursor class methodsFor: 'constants'!
  27833. bottomLeft
  27834.     "Cursor bottomLeft showWhile: [Sensor waitButton]"
  27835.     ^ (Cursor extent: 16@16
  27836.             fromArray: #(
  27837.         2r1100000000000000
  27838.         2r1100000000000000
  27839.         2r1100000000000000
  27840.         2r1100000000000000
  27841.         2r1100000000000000
  27842.         2r1100000000000000
  27843.         2r1100000000000000
  27844.         2r1100000000000000
  27845.         2r1100000000000000
  27846.         2r1100000000000000
  27847.         2r1100000000000000
  27848.         2r1100000000000000
  27849.         2r1100000000000000
  27850.         2r1100000000000000
  27851.         2r1111111111111111
  27852.         2r1111111111111111)
  27853.             offset: 0@-16).
  27854. ! !
  27855.  
  27856. !Cursor class methodsFor: 'constants'!
  27857. bottomRight
  27858.     "Cursor bottomRight showWhile: [Sensor waitButton]"
  27859.     ^ (Cursor extent: 16@16
  27860.             fromArray: #(
  27861.         2r0000000000000011
  27862.         2r0000000000000011
  27863.         2r0000000000000011
  27864.         2r0000000000000011
  27865.         2r0000000000000011
  27866.         2r0000000000000011
  27867.         2r0000000000000011
  27868.         2r0000000000000011
  27869.         2r0000000000000011
  27870.         2r0000000000000011
  27871.         2r0000000000000011
  27872.         2r0000000000000011
  27873.         2r0000000000000011
  27874.         2r0000000000000011
  27875.         2r1111111111111111
  27876.         2r1111111111111111)
  27877.             offset: -16@-16).
  27878. ! !
  27879.  
  27880. !Cursor class methodsFor: 'constants'!
  27881. corner
  27882.     "Answer the instance of me that is the shape of the bottom right corner 
  27883.     of a rectangle."
  27884.  
  27885.     ^CornerCursor! !
  27886.  
  27887. !Cursor class methodsFor: 'constants'!
  27888. crossHair
  27889.     "Answer the instance of me that is the shape of a cross."
  27890.  
  27891.     ^CrossHairCursor! !
  27892.  
  27893. !Cursor class methodsFor: 'constants'!
  27894. down
  27895.     "Answer the instance of me that is the shape of an arrow facing 
  27896.     downward."
  27897.  
  27898.     ^DownCursor! !
  27899.  
  27900. !Cursor class methodsFor: 'constants'!
  27901. execute
  27902.     "Answer the instance of me that is the shape of an arrow slanted left 
  27903.     with a star next to it."
  27904.  
  27905.     ^XeqCursor! !
  27906.  
  27907. !Cursor class methodsFor: 'constants'!
  27908. marker
  27909.     "Answer the instance of me that is the shape of a small ball."
  27910.  
  27911.     ^MarkerCursor! !
  27912.  
  27913. !Cursor class methodsFor: 'constants'!
  27914. menu 
  27915.     "Answer the instance of me that is the shape of a menu."
  27916.  
  27917.     ^MenuCursor! !
  27918.  
  27919. !Cursor class methodsFor: 'constants'!
  27920. move
  27921.     "Answer the instance of me that is the shape of a cross inside a square."
  27922.  
  27923.     ^MoveCursor! !
  27924.  
  27925. !Cursor class methodsFor: 'constants'!
  27926. normal
  27927.     "Answer the instance of me that is the shape of an arrow slanted left."
  27928.  
  27929.     ^NormalCursor! !
  27930.  
  27931. !Cursor class methodsFor: 'constants'!
  27932. origin
  27933.     "Answer the instance of me that is the shape of the top left corner of a 
  27934.     rectangle."
  27935.  
  27936.     ^OriginCursor! !
  27937.  
  27938. !Cursor class methodsFor: 'constants'!
  27939. read
  27940.     "Answer the instance of me that is the shape of eyeglasses."
  27941.  
  27942.     ^ReadCursor! !
  27943.  
  27944. !Cursor class methodsFor: 'constants'!
  27945. rightArrow 
  27946.     "Answer the instance of me that is the shape of an arrow pointing to the right."
  27947.  
  27948.     ^RightArrowCursor! !
  27949.  
  27950. !Cursor class methodsFor: 'constants'!
  27951. square
  27952.     "Answer the instance of me that is the shape of a square."
  27953.  
  27954.     ^SquareCursor! !
  27955.  
  27956. !Cursor class methodsFor: 'constants'!
  27957. topLeft
  27958.     "Cursor topLeft showWhile: [Sensor waitButton]"
  27959.     ^ (Cursor extent: 16@16
  27960.             fromArray: #(
  27961.         2r1111111111111111
  27962.         2r1111111111111111
  27963.         2r1100000000000000
  27964.         2r1100000000000000
  27965.         2r1100000000000000
  27966.         2r1100000000000000
  27967.         2r1100000000000000
  27968.         2r1100000000000000
  27969.         2r1100000000000000
  27970.         2r1100000000000000
  27971.         2r1100000000000000
  27972.         2r1100000000000000
  27973.         2r1100000000000000
  27974.         2r1100000000000000
  27975.         2r1100000000000000
  27976.         2r1100000000000000)
  27977.             offset: 0@0).
  27978. ! !
  27979.  
  27980. !Cursor class methodsFor: 'constants'!
  27981. topRight
  27982.     "Cursor topRight showWhile: [Sensor waitButton]"
  27983.     ^ (Cursor extent: 16@16
  27984.             fromArray: #(
  27985.         2r1111111111111111
  27986.         2r1111111111111111
  27987.         2r0000000000000011
  27988.         2r0000000000000011
  27989.         2r0000000000000011
  27990.         2r0000000000000011
  27991.         2r0000000000000011
  27992.         2r0000000000000011
  27993.         2r0000000000000011
  27994.         2r0000000000000011
  27995.         2r0000000000000011
  27996.         2r0000000000000011
  27997.         2r0000000000000011
  27998.         2r0000000000000011
  27999.         2r0000000000000011
  28000.         2r0000000000000011)
  28001.             offset: -16@0).
  28002. ! !
  28003.  
  28004. !Cursor class methodsFor: 'constants'!
  28005. up
  28006.     "Answer the instance of me that is the shape of an arrow facing upward."
  28007.  
  28008.     ^UpCursor! !
  28009.  
  28010. !Cursor class methodsFor: 'constants' stamp: 'sw 8/15/97 13:28'!
  28011. wait
  28012.     "Answer the instance of me that is the shape of an Hourglass (was in the 
  28013.     shape of three small balls)."
  28014.  
  28015.     ^WaitCursor! !
  28016.  
  28017. !Cursor class methodsFor: 'constants'!
  28018. write
  28019.     "Answer the instance of me that is the shape of a pen writing."
  28020.  
  28021.     ^WriteCursor! !
  28022. Path subclass: #CurveFitter
  28023.     instanceVariableNames: ''
  28024.     classVariableNames: ''
  28025.     poolDictionaries: ''
  28026.     category: 'Graphics-Paths'!
  28027. !CurveFitter commentStamp: 'di 5/22/1998 16:33' prior: 0!
  28028. CurveFitter class comment:
  28029. 'I represent a conic section determined by three points p1,p2 and p3. I interpolate p1 and p3 and am tangent to line p1,p2 at p1 and line p3,p2 at p3.'!
  28030.  
  28031.  
  28032. !CurveFitter methodsFor: 'displaying'!
  28033. displayOn: aDisplayMedium at: aPoint clippingBox: clipRect rule: anInteger fillColor: aForm
  28034.  
  28035.     | pa pb k s p1 p2 p3 line |
  28036.     line _ Line new.
  28037.     line form: self form.
  28038.     collectionOfPoints size < 3 ifTrue: [self error: 'Curve must have three points'].
  28039.     p1 _ self firstPoint.
  28040.     p2 _ self secondPoint.
  28041.     p3 _ self thirdPoint.
  28042.     s _ Path new.
  28043.     s add: p1.
  28044.     pa _ p2 - p1.
  28045.     pb _ p3 - p2.
  28046.     k _ 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20.
  28047.     "k is a guess as to how many line segments to use to approximate 
  28048.     the curve."
  28049.     1 to: k do: 
  28050.         [:i | 
  28051.         s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) // (k - 1)].
  28052.     s add: p3.
  28053.     1 to: s size - 1 do: 
  28054.         [:i | 
  28055.         line beginPoint: (s at: i).
  28056.         line endPoint: (s at: i + 1).
  28057.         line displayOn: aDisplayMedium
  28058.             at: aPoint
  28059.             clippingBox: clipRect
  28060.             rule: anInteger
  28061.             fillColor: aForm]! !
  28062.  
  28063. !CurveFitter methodsFor: 'displaying' stamp: '6/9/97 10:16 di'!
  28064. displayOn: aDisplayMedium transformation: aTransformation clippingBox: clipRect rule: anInteger fillColor: aForm
  28065.  
  28066.     | transformedPath newCurveFitter |
  28067.     transformedPath _ aTransformation applyTo: self.
  28068.     newCurveFitter _ CurveFitter new.
  28069.     newCurveFitter firstPoint: transformedPath firstPoint.
  28070.     newCurveFitter secondPoint: transformedPath secondPoint.
  28071.     newCurveFitter thirdPoint: transformedPath thirdPoint.
  28072.     newCurveFitter form: self form.
  28073.     newCurveFitter
  28074.         displayOn: aDisplayMedium
  28075.         at: 0 @ 0
  28076.         clippingBox: clipRect
  28077.         rule: anInteger
  28078.         fillColor: aForm! !
  28079.  
  28080. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  28081.  
  28082. CurveFitter class
  28083.     instanceVariableNames: ''!
  28084.  
  28085. !CurveFitter class methodsFor: 'instance creation'!
  28086. new
  28087.  
  28088.     | newSelf | 
  28089.     newSelf _ super new: 3.
  28090.     newSelf add: 0@0.
  28091.     newSelf add: 0@0.
  28092.     newSelf add: 0@0.
  28093.     ^newSelf! !
  28094.  
  28095.  
  28096. !CurveFitter class methodsFor: 'examples' stamp: '6/9/97 10:16 di'!
  28097. example
  28098.     "Designate three locations on the screen by clicking any button. The
  28099.     curve determined by the points will be displayed with a long black form."
  28100.  
  28101.     | aCurveFitter aForm |  
  28102.     aForm _ Form extent: 1@30.            "make a long thin Form for display "
  28103.     aForm fillBlack.                            "turn it black"
  28104.     aCurveFitter _ CurveFitter new.
  28105.     aCurveFitter form: aForm.                        "set the form for display"
  28106.                 "collect three Points and show them on the dispaly"
  28107.     aCurveFitter firstPoint: Sensor waitButton. Sensor waitNoButton.
  28108.     aForm displayOn: Display at: aCurveFitter firstPoint.
  28109.     aCurveFitter secondPoint: Sensor waitButton. Sensor waitNoButton.
  28110.     aForm displayOn: Display at: aCurveFitter secondPoint.
  28111.     aCurveFitter thirdPoint: Sensor waitButton. Sensor waitNoButton.
  28112.     aForm displayOn: Display at: aCurveFitter thirdPoint.
  28113.  
  28114.     aCurveFitter displayOn: Display                    "display the CurveFitter"
  28115.  
  28116.     "CurveFitter example"! !
  28117. PolygonMorph subclass: #CurveMorph
  28118.     instanceVariableNames: 'coefficients ntfPoint ntlPoint '
  28119.     classVariableNames: ''
  28120.     poolDictionaries: ''
  28121.     category: 'Morphic-Basic'!
  28122.  
  28123. !CurveMorph methodsFor: 'private' stamp: 'di 9/26/97 10:31'!
  28124. addHandles
  28125.     super addHandles.
  28126.     self updateHandles! !
  28127.  
  28128. !CurveMorph methodsFor: 'private' stamp: '6/9/97 21:28 di'!
  28129. computeCurve
  28130.     "Compute an array for the coefficients.  This is copied from Flegal's old
  28131.     code in the Spline class."
  28132.     | length extras verts |
  28133.     verts _ closed ifTrue: [vertices copyWith: vertices first]
  28134.                 ifFalse: [vertices].
  28135.     length _ verts size.
  28136.     extras _ 0.
  28137.     coefficients _ Array new: 8.
  28138.     1 to: 8 do: [:i | coefficients at: i put: (Array new: length + extras)].
  28139.     1 to: 5 by: 4 do: 
  28140.         [:k | 
  28141.         1 to: length do:
  28142.             [:i | (coefficients at: k)
  28143.                     at: i put: (k = 1
  28144.                         ifTrue: [(verts at: i) x asFloat]
  28145.                         ifFalse: [(verts at: i) y asFloat])].
  28146.             1 to: extras do: [:i | (coefficients at: k)
  28147.                     at: length + i put: ((coefficients at: k)
  28148.                         at: i + 1)].
  28149.             self derivs: (coefficients at: k)
  28150.                 first: (coefficients at: k + 1)
  28151.                 second: (coefficients at: k + 2)
  28152.                 third: (coefficients at: k + 3)].
  28153.     extras > 0 
  28154.         ifTrue: [1 to: 8 do: 
  28155.                     [:i | 
  28156.                     coefficients at: i put: ((coefficients at: i)
  28157.                                             copyFrom: 2 to: length + 1)]]! !
  28158.  
  28159. !CurveMorph methodsFor: 'private' stamp: 'di 12/3/97 11:00'!
  28160. curveBounds
  28161.     "Compute the bounds from actual curve traversal, with leeway for borderWidth.
  28162.     Also note the next-to-first and next-to-last points for arrow directions."
  28163.     | curveBounds |
  28164.     self computeCurve.
  28165.     curveBounds _ vertices first corner: vertices last.
  28166.     ntfPoint _ nil.
  28167.     self lineSegmentsDo:
  28168.         [:p1 :p2 | ntfPoint == nil ifTrue: [ntfPoint _ p2 asIntegerPoint].
  28169.         curveBounds _ curveBounds encompass: p2 asIntegerPoint.
  28170.         ntlPoint _ p1 asIntegerPoint].
  28171.     ^ curveBounds expandBy: borderWidth+1//2! !
  28172.  
  28173. !CurveMorph methodsFor: 'private' stamp: '6/9/97 10:32 di'!
  28174. derivs: a first: point1 second: point2 third: point3
  28175.     "Compute the first, second and third derivitives (in coefficients) from
  28176.     the Points in this Path (coefficients at: 1 and coefficients at: 5)."
  28177.     | len v anArray |
  28178.     len _ a size.
  28179.     len < 2 ifTrue: [^self].
  28180.     len > 2 ifTrue:
  28181.         [v _ Array new: len.
  28182.          v  at: 1 put: 4.0.
  28183.          anArray _ Array new: len.
  28184.          anArray at: 1 put: (6.0 * ((a at: 1) - ((a at: 2) * 2.0) + (a at: 3))).
  28185.          2 to: len - 2 do:
  28186.             [:i | 
  28187.             v  at: i put: (4.0 - (1.0 / (v at: i-1))).
  28188.             anArray at: i 
  28189.                 put: (6.0 * ((a at: i) - ((a at: i+1) * 2.0) + (a at: i+2))
  28190.                         - ((anArray at: i-1) / (v at: i-1)))].
  28191.          point2 at: len-1 put: ((anArray at: len-2) / (v at: len-2)).
  28192.          len - 2 to: 2 by: 0-1 do: 
  28193.             [:i | 
  28194.             point2 at: i 
  28195.                 put: ((anArray at: i-1) - (point2 at: i+1) / (v at: i-1))]].
  28196.     point2 at: 1 put: (point2 at: len put: 0.0).
  28197.     1 to: len - 1 do:
  28198.         [:i | point1 at: i 
  28199.                 put: ((a at: i+1) - (a at: i) - 
  28200.                         ((point2 at: i) * 2.0 + (point2 at: i+1) / 6.0)).
  28201.               point3 at: i put: ((point2 at: i+1) - (point2 at: i))]! !
  28202.  
  28203. !CurveMorph methodsFor: 'private' stamp: 'di 12/4/97 09:45'!
  28204. isCurve
  28205.     ^ true! !
  28206.  
  28207. !CurveMorph methodsFor: 'private' stamp: 'di 11/29/97 20:54'!
  28208. lineSegmentsDo: endPointsBlock
  28209.     "Emit a sequence of line segments into endPointsBlock to approximate this spline."
  28210.     | n t x y x1 x2 x3 y1 y2 y3 beginPoint endPoint |
  28211.     vertices size < 1 ifTrue: [^ self].
  28212.     beginPoint _ (x _ (coefficients at: 1) at: 1) @ (y _ (coefficients at: 5) at: 1).
  28213.     1 to: (coefficients at: 1) size - 1 do: 
  28214.         [:i |  "taylor series coefficients"
  28215.         x1 _ (coefficients at: 2) at: i.
  28216.         y1 _ (coefficients at: 6) at: i.
  28217.         x2 _ ((coefficients at: 3) at: i) / 2.0.
  28218.         y2 _ ((coefficients at: 7) at: i) / 2.0.
  28219.         x3 _ ((coefficients at: 4) at: i) / 6.0.
  28220.         y3 _ ((coefficients at: 8) at: i) / 6.0.
  28221.         "guess n"
  28222.         n _ 5 max: (x2 abs + y2 abs * 2.0 + ((coefficients at: 3) at: i+1) abs
  28223.                                     + ((coefficients at: 7) at: i+1) abs / 100.0) rounded.
  28224.         1 to: n - 1 do: 
  28225.             [:j | 
  28226.             t _ j asFloat / n.
  28227.             endPoint _ (x3 * t + x2 * t + x1 * t + x) @ (y3 * t + y2 * t + y1 * t + y).
  28228.             endPointsBlock value: beginPoint
  28229.                             value: endPoint.
  28230.             beginPoint _ endPoint].
  28231.         endPoint _ (x _ (coefficients at: 1) at: i+1) @ (y _ (coefficients at: 5) at: i+1).
  28232.         endPointsBlock value: beginPoint
  28233.                         value: endPoint.
  28234.         beginPoint _ endPoint]! !
  28235.  
  28236. !CurveMorph methodsFor: 'private' stamp: '6/9/97 12:08 di'!
  28237. nextToFirstPoint  "For arrow direction"
  28238.     ^ ntfPoint! !
  28239.  
  28240. !CurveMorph methodsFor: 'private' stamp: '6/9/97 12:08 di'!
  28241. nextToLastPoint  "For arrow direction"
  28242.     ^ ntlPoint! !
  28243.  
  28244. !CurveMorph methodsFor: 'private' stamp: '6/9/97 13:57 di'!
  28245. privateMoveBy: delta
  28246.     super privateMoveBy: delta.
  28247.     self computeCurve! !
  28248.  
  28249. !CurveMorph methodsFor: 'private' stamp: 'di 1/26/98 23:54'!
  28250. updateHandles
  28251.     | midPts nextVertIx tweens newVert p2i |
  28252.     midPts _ OrderedCollection new.
  28253.     nextVertIx _ 2.
  28254.     tweens _ OrderedCollection new.
  28255.     self lineSegmentsDo:
  28256.         [:p1 :p2 | p2i _ p2 asIntegerPoint.
  28257.         tweens addLast: p2i.
  28258.         p2i = (vertices atWrap: nextVertIx) ifTrue:
  28259.             ["Found endPoint."
  28260.             midPts addLast: (tweens at: tweens size // 2)
  28261.                         + (tweens at: tweens size + 1 // 2) // 2.
  28262.             tweens _ OrderedCollection new.
  28263.             nextVertIx _ nextVertIx + 1]].
  28264.     midPts withIndexDo:
  28265.         [:midPt :vertIndex |
  28266.         (closed or: [vertIndex < vertices size]) ifTrue:
  28267.             [newVert _ handles at: vertIndex*2.
  28268.             newVert position: midPt - (newVert extent // 2)]].! !
  28269. SelectionMenu subclass: #CustomMenu
  28270.     instanceVariableNames: 'labels dividers lastDivider '
  28271.     classVariableNames: ''
  28272.     poolDictionaries: ''
  28273.     category: 'Interface-Menus'!
  28274. !CustomMenu commentStamp: 'di 5/22/1998 16:33' prior: 0!
  28275. CustomMenu comment:
  28276. 'I am used to build menus on-the-fly. I maintain lists of menu items, actions (usually symbols to be sent as messages), and menu section dividing lines to which my clients may append new entries and lines by sending me the messages:
  28277.  
  28278.     add: aString action: anAction
  28279.     addLine
  28280.  
  28281. After the menu is constructed, it may be invoked with one of the following messages:
  28282.  
  28283.     invoke: initialSelection
  28284.     invoke
  28285.  
  28286. I am a subclass of ActionMenu, so I inherit a number of instance variables. The ones I am particularly concerned with are:
  28287.  
  28288.     items _ an OrderedCollection of strings to appear in the menu
  28289.     selectors _ an OrderedCollection of Symbols to be used as message selectors
  28290.     lineArray _ an OrderedCollection of line positions
  28291.     lastLine _ used to keep track of the last line to avoid making duplicate entries in lineArray'!
  28292.  
  28293.  
  28294. !CustomMenu methodsFor: 'initialize-release'!
  28295. initialize
  28296.  
  28297.     labels _ OrderedCollection new.
  28298.     selections _ OrderedCollection new.
  28299.     dividers _ OrderedCollection new.
  28300.     lastDivider _ 0.! !
  28301.  
  28302.  
  28303. !CustomMenu methodsFor: 'construction'!
  28304. add: aString action: actionItem
  28305.     "Add the given string as the next menu item. If it is selected, the given action (usually but not necessarily a symbol) will be returned to the client."
  28306.  
  28307.     | s |
  28308.     s _ String new: aString size + 2.
  28309.     s at: 1 put: Character space.
  28310.     s replaceFrom: 2 to: s size - 1 with: aString.
  28311.     s at: s size put: Character space.
  28312.     labels addLast: s.
  28313.     selections addLast: actionItem.! !
  28314.  
  28315. !CustomMenu methodsFor: 'construction'!
  28316. addLine
  28317.     "Append a line to the menu after the last entry. Suppress duplicate lines."
  28318.  
  28319.     (lastDivider ~= selections size) ifTrue: [
  28320.         lastDivider _ selections size.
  28321.         dividers addLast: lastDivider].! !
  28322.  
  28323. !CustomMenu methodsFor: 'construction' stamp: 'jm 3/29/98 07:09'!
  28324. addList: listOfPairs
  28325.     "Add a menu item to the receiver for each pair in the given list of the form (<what to show> <selector>). Add a line for each dash (-) in the list."
  28326.     "CustomMenu new addList: #(
  28327.         ('apples' buyApples)
  28328.         ('oranges' buyOranges)
  28329.         -
  28330.         ('milk' buyMilk)); startUp"
  28331.  
  28332.     listOfPairs do: [:pair |
  28333.         #- = pair
  28334.             ifTrue: [self addLine]
  28335.             ifFalse: [self add: pair first action: pair last]].
  28336. ! !
  28337.  
  28338. !CustomMenu methodsFor: 'construction' stamp: 'jm 5/6/1998 19:47'!
  28339. labels: aString lines: linesArray selections: selectionsArray
  28340.     "This method allows the receiver to accept old-style SelectionMenu creation messages. It should be used only for backward compatibility during the MVC-to-Morphic transition. New code should be written using the other menu construction protocol such as addList:."
  28341.  
  28342.     | labelList |
  28343.     labelList _ (aString findTokens: String cr) asArray.
  28344.     1 to: labelList size do: [:i |
  28345.         self add: (labelList at: i) action: (selectionsArray at: i).
  28346.         (linesArray includes: i) ifTrue: [self addLine]].
  28347. ! !
  28348.  
  28349.  
  28350. !CustomMenu methodsFor: 'invocation' stamp: 'jm 11/17/97 16:54'!
  28351. invokeOn: targetObject defaultSelection: defaultSelection
  28352.     "Invoke the menu with the given default selection (i.e. one of my 'action' symbols). Answer the 'action' selector associated with the menu item chosen by the user or nil if none is chosen."
  28353.  
  28354.     | sel |
  28355.     sel _ self startUp: defaultSelection.
  28356.     sel = nil ifFalse: [
  28357.         sel numArgs = 0
  28358.             ifTrue: [^ targetObject perform: sel]
  28359.             ifFalse: [^ targetObject perform: sel with: nil]].
  28360.     ^ nil
  28361. ! !
  28362.  
  28363. !CustomMenu methodsFor: 'invocation'!
  28364. startUp
  28365.     "Build and invoke this menu with no initial selection. Answer the selection associated with the menu item chosen by the user or nil if none is chosen."
  28366.  
  28367.     ^ self startUp: nil! !
  28368.  
  28369. !CustomMenu methodsFor: 'invocation'!
  28370. startUp: initialSelection
  28371.     "Build and invoke this menu with the given initial selection. Answer the selection associated with the menu item chosen by the user or nil if none is chosen."
  28372.  
  28373.     ^ self startUp: initialSelection withCaption: nil! !
  28374.  
  28375. !CustomMenu methodsFor: 'invocation'!
  28376. startUp: initialSelection withCaption: caption
  28377.     "Build and invoke this menu with the given initial selection and caption. Answer the selection associated with the menu item chosen by the user or nil if none is chosen."
  28378.  
  28379.     self build.
  28380.     (initialSelection notNil) ifTrue: [self preSelect: initialSelection].
  28381.     ^ super startUpWithCaption: caption! !
  28382.  
  28383. !CustomMenu methodsFor: 'invocation' stamp: 'sw 7/31/97 19:31'!
  28384. startUpWithCaption: caption
  28385.     "Build and invoke this menu with no initial selection. Answer the selection associated with the menu item chosen by the user or nil if none is chosen; use the provided caption"
  28386.  
  28387.     ^ self startUp: nil withCaption: caption! !
  28388.  
  28389.  
  28390. !CustomMenu methodsFor: 'private'!
  28391. build
  28392.     "Turn myself into an invokable ActionMenu."
  28393.  
  28394.     | stream |
  28395.     stream _ WriteStream on: (String new).
  28396.     labels do: [: label | stream nextPutAll: label; cr].
  28397.     (labels isEmpty) ifFalse: [stream skip: -1].  "remove final cr"
  28398.     self labels: stream contents
  28399.         font: (TextStyle default fontAt: 1)
  28400.         lines: dividers.! !
  28401.  
  28402. !CustomMenu methodsFor: 'private'!
  28403. preSelect: action
  28404.     "Pre-select and highlight the menu item associated with the given action."
  28405.  
  28406.     | i |
  28407.     i _ selections indexOf: action ifAbsent: [^ self].
  28408.     marker _ marker
  28409.         align: marker topLeft
  28410.         with: (marker left)@(frame inside top + (marker height * (i - 1))).
  28411.     selection _ i.! !
  28412.  
  28413. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  28414.  
  28415. CustomMenu class
  28416.     instanceVariableNames: ''!
  28417.  
  28418. !CustomMenu class methodsFor: 'instance creation'!
  28419. new
  28420.  
  28421.     ^ super new initialize! !
  28422.  
  28423.  
  28424. !CustomMenu class methodsFor: 'example'!
  28425. example
  28426.     "CustomMenu example"
  28427.  
  28428.     | menu |
  28429.     menu _ CustomMenu new.
  28430.     menu add: 'apples' action: #apples.
  28431.     menu add: 'oranges' action: #oranges.
  28432.     menu addLine.
  28433.     menu addLine.  "extra lines ignored"
  28434.     menu add: 'peaches' action: #peaches.
  28435.     menu addLine.
  28436.     menu add: 'pears' action: #pears.
  28437.     menu addLine.
  28438.     ^ menu startUp: #apples! !
  28439. Object subclass: #DamageRecorder
  28440.     instanceVariableNames: 'invalidRects totalRepaint '
  28441.     classVariableNames: ''
  28442.     poolDictionaries: ''
  28443.     category: 'Morphic-Support'!
  28444.  
  28445. !DamageRecorder methodsFor: 'all'!
  28446. doFullRepaint
  28447.     "Record that a full redisplay is needed. No further damage rectangles will be recorded until after the next reset."
  28448.  
  28449.     ^ totalRepaint _ true.
  28450. ! !
  28451.  
  28452. !DamageRecorder methodsFor: 'all'!
  28453. invalidRectsFullBounds: aRectangle
  28454.     "Return a collection of damaged rectangles for the given canvas. If a total repaint has been requested, return the given rectangle."
  28455.  
  28456.     totalRepaint
  28457.         ifTrue: [^ Array with: aRectangle]
  28458.         ifFalse: [^ invalidRects copy].
  28459.  
  28460. ! !
  28461.  
  28462. !DamageRecorder methodsFor: 'all' stamp: 'jm 5/22/1998 14:07'!
  28463. recordInvalidRect: aRectangle
  28464.     "Record the given rectangle in my damage list, a list of rectagular areas of the display that should be redraw on the next display cycle."
  28465.     "Details: Damaged rectangles are often identical or overlap significantly. In these cases, we merge them to reduce the number of damage rectangles that must be processed when the display is updated. Moreover, above a certain threshold, we ignore the individual rectangles completely, and simply do a complete repaint on the next cycle."
  28466.  
  28467.     | mergeRect |
  28468.     totalRepaint ifTrue: [^ self].  "planning full repaint; don't bother collecting damage"
  28469.  
  28470.     invalidRects do: [:rect |
  28471.         (rect intersects: aRectangle) ifTrue: [
  28472.             "merge rectangle in place (see note below) if there is any overlap"
  28473.             rect setOrigin: (rect origin min: aRectangle origin) truncated
  28474.                 corner: (rect corner max: aRectangle corner) truncated.
  28475.             ^ self]].
  28476.  
  28477.  
  28478.     invalidRects size >= 10 ifTrue: [
  28479.         "if there are too many separate areas, just repaint all"
  28480.         "totalRepaint _ true."
  28481. "Note:  The totalRepaint policy has poor behavior when many local rectangles (such as parts of a text selection) force repaint of the entire screen.  As an alternative, this code performs a simple merge of all rects whenever there are more than 10."
  28482.         mergeRect _ Rectangle merging: invalidRects.
  28483.         self reset.
  28484.         invalidRects addLast: mergeRect].
  28485.  
  28486.     "add the given rectangle to the damage list"
  28487.     "Note: We make a deep copy of all rectangles added to the damage list,
  28488.      since rectangles in this list may be extended in place."
  28489.     invalidRects addLast: (aRectangle topLeft truncated corner: aRectangle bottomRight truncated).
  28490. ! !
  28491.  
  28492. !DamageRecorder methodsFor: 'all'!
  28493. reset
  28494.     "Clear the damage list."
  28495.  
  28496.     invalidRects _ OrderedCollection new.
  28497.     totalRepaint _ false.
  28498. ! !
  28499.  
  28500. !DamageRecorder methodsFor: 'all'!
  28501. updateIsNeeded
  28502.     "Return true if the display needs to be updated."
  28503.  
  28504.     ^ totalRepaint or: [invalidRects size > 0]
  28505. ! !
  28506.  
  28507. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  28508.  
  28509. DamageRecorder class
  28510.     instanceVariableNames: ''!
  28511.  
  28512. !DamageRecorder class methodsFor: 'instance creation'!
  28513. new
  28514.  
  28515.     ^ super new reset
  28516. ! !
  28517. UpdatingStringMorph subclass: #DataMorph
  28518.     instanceVariableNames: 'dataType status '
  28519.     classVariableNames: ''
  28520.     poolDictionaries: ''
  28521.     category: 'Experimental-Miscellaneous'!
  28522. !DataMorph commentStamp: 'di 5/22/1998 16:33' prior: 0!
  28523. A morph representing data to be borne by a slot encompassing pasteUpMorph, as a step toward a stack/card architecture.  This is work in progress, and should be approached with the mose extreme caution.!
  28524.  
  28525.  
  28526. !DataMorph methodsFor: 'all' stamp: 'sw 5/2/1998 16:55'!
  28527. becomeField
  28528.     | aStack slotNameChosen  |
  28529.     aStack _ self pasteUpMorph assuredCostumee.
  28530.  
  28531.     slotNameChosen _ aStack addSlotNamedLike: self externalName withValue: self valueFromContents.
  28532.  
  28533.     self getSelector: (Utilities getterSelectorFor: slotNameChosen).
  28534.     self putSelector: (Utilities setterSelectorFor: slotNameChosen).
  28535.     self target: aStack.
  28536.     status _ #field.
  28537.     aStack updateAllViewers! !
  28538.  
  28539. !DataMorph methodsFor: 'all' stamp: 'sw 5/8/1998 13:41'!
  28540. dockUpToInstance: anInstance
  28541.     "The enclosing PasteUpMorph's current instance has changed (i.e., a new card is been 'gone to'), so do what is necessary"
  28542.     | oldTarget |
  28543.     self flag: #deferred.  "Not ready for use"
  28544.     oldTarget _ target.
  28545.     target _ anInstance.
  28546.     self  readFromTarget.
  28547.     contents == nil ifTrue: [contents _ '<new>'].
  28548.     getSelector == nil ifTrue: [self isThisEverCalled].
  28549.     oldTarget == target ifFalse: [oldTarget updateAllViewers]! !
  28550.  
  28551. !DataMorph methodsFor: 'all' stamp: 'sw 5/2/1998 17:18'!
  28552. drawOn: aCanvas
  28553.     | borderColorToUse |
  28554.     borderColorToUse _ status == #field
  28555.         ifTrue:
  28556.             [Color blue muchLighter]
  28557.         ifFalse:
  28558.             [Color red lighter].
  28559.     aCanvas frameAndFillRectangle: bounds
  28560.         fillColor: Color blue veryMuchLighter
  28561.         borderWidth: 1
  28562.         borderColor: borderColorToUse.
  28563.  
  28564.     super drawOn: aCanvas.! !
  28565.  
  28566. !DataMorph methodsFor: 'all' stamp: 'sw 4/27/1998 19:04'!
  28567. holdsDataForEachInstance
  28568.     ^ status == #field! !
  28569.  
  28570. !DataMorph methodsFor: 'all' stamp: 'sw 5/6/1998 16:32'!
  28571. initializeAsAuthoringPrototypeOfType: typeSymbol
  28572.     dataType _ typeSymbol.
  28573.      typeSymbol == #string
  28574.         ifTrue:
  28575.             [self useStringFormat]
  28576.         ifFalse:
  28577.             [self useDefaultFormat].
  28578.     status _ #field.
  28579.     lastValue _ contents _ 'Data'.
  28580.     self setNameTo: 'field'! !
  28581.  
  28582. !DataMorph methodsFor: 'all' stamp: 'sw 5/6/1998 16:41'!
  28583. setLiteral: anObject
  28584.     "Like much else here, not yet in service"
  28585.     dataType _ #literal.
  28586.     lastValue _ anObject.
  28587.     contents _ anObject
  28588. ! !
  28589.  
  28590. !DataMorph methodsFor: 'all' stamp: 'sw 4/27/1998 16:58'!
  28591. wantsKeyboardFocusFor: aSubmorph
  28592.     ^ self inPartsBin not! !
  28593.  
  28594. !DataMorph methodsFor: 'all' stamp: 'sw 5/6/1998 16:33'!
  28595. wouldAcceptKeyboardFocus
  28596.     ^ self inPartsBin not! !
  28597.  
  28598. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  28599.  
  28600. DataMorph class
  28601.     instanceVariableNames: ''!
  28602.  
  28603. !DataMorph class methodsFor: 'as yet unclassified' stamp: 'sw 4/27/1998 16:32'!
  28604. authoringPrototype
  28605.     ^ self new initializeAsAuthoringPrototypeOfType: #string! !
  28606. Stream subclass: #DataStream
  28607.     instanceVariableNames: 'byteStream topCall basePos '
  28608.     classVariableNames: 'TypeMap '
  28609.     poolDictionaries: ''
  28610.     category: 'System-Object Storage'!
  28611. !DataStream commentStamp: 'di 5/22/1998 16:33' prior: 0!
  28612. DataStream comment:
  28613. 'This is the save-to-disk facility. A DataStream can store one or more objects in a persistent form.
  28614.  
  28615. To handle objects with sharing and cycles, you must use a
  28616. ReferenceStream instead of a DataStream.  (Or SmartRefStream.)  ReferenceStream is typically
  28617. faster and produces smaller files because it doesn''t repeatedly write the same Symbols.
  28618.  
  28619. Here is the way to use DataStream and ReferenceStream:
  28620.     rr _ ReferenceStream fileNamed: ''test.obj''.
  28621.     rr nextPut: <your object>.
  28622.     rr close.
  28623.  
  28624. To get it back:
  28625.     rr _ ReferenceStream fileNamed: ''test.obj''.
  28626.     <your object> _ rr next.
  28627.     rr close.
  28628.  
  28629. Each object to be stored has two opportunities to control what gets stored. The high level, more useful hook is objectToStoreOnDataStream [externalize]. The low level hook is storeDataOn:. The read-in counterparts to these messages are comeFullyUpOnReload [internalize] and (class) readDataFrom:size:. See these methods, the class DiskProxy, and the class IOWeakArray for more information about externalizing and internalizing.
  28630.  
  28631. Public messages:
  28632.     (class) on:
  28633.     (class) fileNamed:
  28634.     (class) fileTypeCode
  28635.     atEnd
  28636.     beginInstance:size: (for use by storeDataOn: methods)
  28637.     beginReference: (for use by readDataFrom:size: methods)
  28638.     close
  28639.     next
  28640.     next:
  28641.     nextPut:
  28642.     nextPutAll:
  28643.     reset
  28644.     setType:
  28645.     size
  28646.  
  28647. NOTE: A DataStream should be treated as a read-stream *or* as a
  28648. write-stream, *not* as a read/write-stream.
  28649.  
  28650. [TBD] We should be able to make this much faster via tight-loop
  28651. byte-string I/O. It looks like FileStream (and WriteStream)
  28652. nextPutAll: do a reasonable job *if* it doesn''t have to push the
  28653. writeLimit, in which case it iterates with nextPut:. It could in many
  28654. cases set the writeLimit and then use the fast case
  28655. (replaceFrom:to:with:startingAt:), or fill a buffer at at time via
  28656. the fast case working on a substring.
  28657.     This approach would handle Strings, ByteArrays, and all other
  28658. variable-byte classes. If(nextPutAll: aCollection) in some cases
  28659. still reverts to (aCollection do: [:e | self nextPut: e]), then we''d
  28660. want to make Obj respond to do:. Then we could speed up inner
  28661. loop activities like nextPutInt32:.
  28662.  
  28663. [TBD] Every DataStream should begin with 4 signature bytes.
  28664. "on:" should emit or check the signature. But the current mechanism doesn''t always
  28665. know when the stream is started or ended.
  28666.  
  28667. [TBD] Cf. notes in DataStream>>beginInstance:size: and
  28668. Object>>readDataFrom:size:.
  28669.  
  28670. [TBD] We could save disk space & I/O time by using short, 1-byte size
  28671. fields whenever possible. E.g. almost all Symbols are shorter than
  28672. 256 chars. We could do this either by (1) using different typeID codes
  28673. to indicate when a 1-byte length follows, a scheme which could still
  28674. read all the old files but would take more code, or (2) a
  28675. variable-length code for sizes.
  28676.     -- 11/15/92 jhm'!
  28677.  
  28678.  
  28679. !DataStream methodsFor: 'all'!
  28680. atEnd
  28681.     "Answer true if the stream is at the end."
  28682.  
  28683.     ^ byteStream atEnd! !
  28684.  
  28685. !DataStream methodsFor: 'all' stamp: '6/9/97 08:14 tk'!
  28686. beginInstance: aClass size: anInteger
  28687.     "This is for use by storeDataOn: methods.
  28688.      Cf. Object>>storeDataOn:."
  28689.  
  28690.         "Addition of 1 seems to make extra work, since readInstance
  28691.         has to compensate.  Here for historical reasons dating back
  28692.         to Kent Beck's original implementation in late 1988.
  28693.  
  28694.         In ReferenceStream, class is just 5 bytes for shared symbol.
  28695.  
  28696.         SmartRefStream puts out the names and number of class's instances variables for checking."
  28697.  
  28698.     byteStream nextNumber: 4 put: anInteger + 1.
  28699.  
  28700.     self nextPut: aClass name! !
  28701.  
  28702. !DataStream methodsFor: 'all'!
  28703. beginReference: anObject
  28704.     "We’re starting to read anObject. Remember it and its reference
  28705.      position (if we care; ReferenceStream cares). Answer the
  28706.      reference position."
  28707.  
  28708.     ^ 0! !
  28709.  
  28710. !DataStream methodsFor: 'all'!
  28711. byteStream
  28712.     ^ byteStream! !
  28713.  
  28714. !DataStream methodsFor: 'all' stamp: 'tk 8/16/96'!
  28715. checkForPaths: anObject
  28716.     "After an object is fully internalized, it should have no PathFromHome in it.    The only exception is Array, as pointed to by an IncomingObjects.  "
  28717.     | pfh |
  28718.     pfh _ Smalltalk at: #PathFromHome ifAbsent: [^ self].
  28719.     1 to: anObject class instSize do:
  28720.         [:i | (anObject instVarAt: i) class == pfh ifTrue: [
  28721.             self error: 'Unresolved Path']].
  28722. ! !
  28723.  
  28724. !DataStream methodsFor: 'all'!
  28725. close
  28726.     "Close the stream."
  28727.  
  28728.     | bytes |
  28729.     byteStream closed 
  28730.         ifFalse: [
  28731.             bytes _ byteStream position.
  28732.             byteStream close]
  28733.         ifTrue: [bytes _ 'unknown'].
  28734.     ^ bytes! !
  28735.  
  28736. !DataStream methodsFor: 'all'!
  28737. errorWriteReference: anInteger
  28738.     "PRIVATE -- Raise an error because this case of nextPut:’s perform:
  28739.      shouldn't be called. -- 11/15/92 jhm"
  28740.  
  28741.     self error: 'This should never be called'! !
  28742.  
  28743. !DataStream methodsFor: 'all'!
  28744. flush
  28745.     "Guarantee that any writes to me are actually recorded on disk. -- 11/17/92 jhm"
  28746.  
  28747.     ^ byteStream flush! !
  28748.  
  28749. !DataStream methodsFor: 'all'!
  28750. getCurrentReference
  28751.     "PRIVATE -- Return the currentReference posn.
  28752.      Overridden by ReferenceStream."
  28753.  
  28754.     ^ 0! !
  28755.  
  28756. !DataStream methodsFor: 'all'!
  28757. internalize: externalObject
  28758.     "PRIVATE -- We just read externalObject. Give it a chance to
  28759.         internalize. Return the internalized object."
  28760.  
  28761.     ^ externalObject comeFullyUpOnReload! !
  28762.  
  28763. !DataStream methodsFor: 'all' stamp: 'tk 7/24/97 18:29'!
  28764. next
  28765.     "Answer the next object in the stream."
  28766.     | type selector anObject isARefType pos |
  28767.  
  28768.     type _ byteStream next.
  28769.     type ifNil: [pos _ byteStream position.    "absolute!!!!"
  28770.         byteStream close.    "clean up"
  28771.         byteStream position = 0 
  28772.             ifTrue: [self error: 'The file did not exist in this directory'] 
  28773.             ifFalse: [self error: 'Unexpected end of object file'].
  28774.         pos.    "so can see it in debugger"
  28775.         ^ nil].
  28776.     type = 0 ifTrue: [pos _ byteStream position.    "absolute!!!!"
  28777.         byteStream close.    "clean up"
  28778.         self error: 'Expected start of object, but found 0'.
  28779.         ^ nil].
  28780.     isARefType _ self noteCurrentReference: type.
  28781.     selector _ #(readNil readTrue readFalse readInteger
  28782.             readString readSymbol readByteArray
  28783.             readArray readInstance readReference readBitmap
  28784.             readClass readUser readFloat readRectangle readShortInst) at: type.
  28785.     anObject _ self perform: selector. "A method that recursively
  28786.         calls next (readArray, readInstance, objectAt:) must save &
  28787.         restore the current reference position."
  28788.     false ifTrue: ["So Senders will find the perform: here"
  28789.             self readNil; readTrue; readFalse; readInteger;
  28790.             readString; readSymbol; readByteArray;
  28791.             readArray; readInstance; readReference; readBitmap;
  28792.             readClass; readUser; readFloat; readRectangle; readShortInst].
  28793.     isARefType ifTrue: [self beginReference: anObject].
  28794.  
  28795.     "After reading the externalObject, internalize it.
  28796.      #readReference is a special case. Either:
  28797.        (1) We actually have to read the object, recursively calling
  28798.            next, which internalizes the object.
  28799.        (2) We just read a reference to an object already read and
  28800.            thus already interalized.
  28801.      Either way, we must not re-internalize the object here."
  28802.     selector == #readReference ifFalse:
  28803.         [anObject _ self internalize: anObject.
  28804.         self checkForPaths: anObject].
  28805.     ^ anObject! !
  28806.  
  28807. !DataStream methodsFor: 'all'!
  28808. next: anInteger
  28809.     "Answer an Array of the next anInteger objects in the stream."
  28810.     | array |
  28811.  
  28812.     array _ Array new: anInteger.
  28813.     1 to: anInteger do: [:i |
  28814.         array at: i put: self next].
  28815.     ^ array! !
  28816.  
  28817. !DataStream methodsFor: 'all' stamp: 'tk 11/24/97 16:31'!
  28818. nextAndClose
  28819.     "Speedy way to grab one object.  Only use when we are inside an object binary file.  Do not use for the start of a SmartRefStream mixed code-and-object file."
  28820.  
  28821.     | obj |
  28822.     byteStream peek = 4 ifFalse: ["Try to fix the user's sins..."
  28823.         self inform: 'Should be using fileInObjectAndCode'.
  28824.         byteStream ascii.
  28825.         byteStream fileIn.
  28826.         obj _ SmartRefStream scannedObject.
  28827.         SmartRefStream scannedObject: nil.
  28828.         ^ obj].
  28829.  
  28830.     obj _ self next.
  28831.     self close.
  28832.     ^ obj! !
  28833.  
  28834. !DataStream methodsFor: 'all' stamp: 'tk 3/13/98 22:16'!
  28835. nextPut: anObject
  28836.     "Write anObject to the receiver stream. Answer anObject.
  28837.      NOTE: If anObject is a reference type (one that we write cross-references to) but its externalized form (result of objectToStoreOnDataStream) isn't (e.g. CompiledMethod and ViewState), then we should remember its externalized form
  28838.  but not add to 'references'. Putting that object again should just put its
  28839.  external form again. That's more compact and avoids seeks when reading.
  28840.  But we just do the simple thing here, allowing backward-references for
  28841.  non-reference types like nil. So objectAt: has to compensate. Objects that
  28842.  externalize nicely won't contain the likes of ViewStates, so this shouldn't
  28843.  hurt much.
  28844.      : writeReference: -> errorWriteReference:."
  28845.     | typeID selector objectToStore |
  28846.  
  28847.     typeID _ self typeIDFor: anObject.
  28848.     (self tryToPutReference: anObject typeID: typeID)
  28849.         ifTrue: [^ anObject].
  28850.  
  28851.     objectToStore _ (self objectIfBlocked: anObject) objectToStoreOnDataStream.
  28852.     objectToStore == anObject ifFalse: [typeID _ self typeIDFor: objectToStore].
  28853.  
  28854.     byteStream nextPut: typeID.
  28855.     selector _ #(writeNil: writeTrue: writeFalse: writeInteger: 
  28856.         writeString: writeSymbol: writeByteArray:
  28857.         writeArray: writeInstance: errorWriteReference: writeBitmap:
  28858.         writeClass: writeUser: writeFloat: writeRectangle: == "dummy 16" ) at: typeID.
  28859.     self perform: selector with: objectToStore.
  28860.  
  28861.     ^ anObject! !
  28862.  
  28863. !DataStream methodsFor: 'all'!
  28864. nextPutAll: aCollection
  28865.     "Write each of the objects in aCollection to the
  28866.      receiver stream. Answer aCollection."
  28867.  
  28868.     ^ aCollection do: [:each | self nextPut: each]! !
  28869.  
  28870. !DataStream methodsFor: 'all'!
  28871. noteCurrentReference: typeID
  28872.     "PRIVATE -- If we support references for type typeID, remember
  28873.      the current byteStream position so we can add the next object to
  28874.      the ‘objects’ dictionary, and return true. Else return false.
  28875.      This method is here to be overridden by ReferenceStream"
  28876.  
  28877.     ^ false! !
  28878.  
  28879. !DataStream methodsFor: 'all' stamp: ' 
  28880.     6/9/97'!
  28881. objectAt: anInteger
  28882.     "PRIVATE -- Read & return the object at a given stream position.  08:18 tk  anInteger is a relative file position. "
  28883.     | savedPosn anObject refPosn |
  28884.  
  28885.     savedPosn _ byteStream position.    "absolute"
  28886.     refPosn _ self getCurrentReference.    "relative position"
  28887.  
  28888.     byteStream position: anInteger + basePos.    "was relative"
  28889.     anObject _ self next.
  28890.  
  28891.     self setCurrentReference: refPosn.    "relative position"
  28892.     byteStream position: savedPosn.        "absolute"
  28893.     ^ anObject! !
  28894.  
  28895. !DataStream methodsFor: 'all' stamp: 'tk 3/13/98 22:16'!
  28896. objectIfBlocked: anObject
  28897.     "We don't do any blocking"
  28898.  
  28899.     ^ anObject! !
  28900.  
  28901. !DataStream methodsFor: 'all' stamp: '6/9/97 08:46 tk'!
  28902. outputReference: referencePosn
  28903.     "PRIVATE -- Output a reference to the object at integer stream position referencePosn (relative to basePos). To output a weak reference to an object not yet written, supply (self vacantRef) for referencePosn."
  28904.  
  28905.     byteStream nextPut: 10. "reference typeID"
  28906.     byteStream nextNumber: 4 put: referencePosn    "relative position"! !
  28907.  
  28908. !DataStream methodsFor: 'all' stamp: '6/9/97 08:32 tk'!
  28909. readArray
  28910.     "PRIVATE -- Read the contents of an Array.
  28911.      We must do beginReference: here after instantiating the Array
  28912.      but before reading its contents, in case the contents reference
  28913.      the Array. beginReference: will be sent again when we return to
  28914.      next, but that's ok as long as we save and restore the current
  28915.      reference position over recursive calls to next."
  28916.     | count array refPosn |
  28917.  
  28918.     count _ byteStream nextNumber: 4.
  28919.  
  28920.     refPosn _ self beginReference: (array _ Array new: count).        "relative pos"
  28921.     1 to: count do: [:i |
  28922.         array at: i put: self next].
  28923.     self setCurrentReference: refPosn.        "relative pos"
  28924.     ^ array! !
  28925.  
  28926. !DataStream methodsFor: 'all'!
  28927. readBitmap
  28928.     "PRIVATE -- Read the contents of a Bitmap."
  28929.  
  28930.     ^ Bitmap newFromStream: byteStream
  28931.     "Note that the reader knows that the size is in long words, but the data is in bytes."! !
  28932.  
  28933. !DataStream methodsFor: 'all'!
  28934. readBoolean
  28935.     "PRIVATE -- Read the contents of a Boolean.
  28936.      This is here only for compatibility with old data files."
  28937.  
  28938.     ^ byteStream next ~= 0! !
  28939.  
  28940. !DataStream methodsFor: 'all'!
  28941. readByteArray
  28942.     "PRIVATE -- Read the contents of a ByteArray."
  28943.     | count buffer |
  28944.  
  28945.     count _ byteStream nextNumber: 4.
  28946.     ^ (ByteArray new: count)
  28947.         replaceFrom: 1 to: count with: (byteStream next: count)! !
  28948.  
  28949. !DataStream methodsFor: 'all' stamp: 'tk 3/24/98 10:29'!
  28950. readClass
  28951.     "Should never be executed because a DiskProxy, not a clas comes in."
  28952.  
  28953.     ^ self error: 'Classes should be filed in'! !
  28954.  
  28955. !DataStream methodsFor: 'all'!
  28956. readFalse
  28957.     "PRIVATE -- Read the contents of a False."
  28958.  
  28959.     ^ false! !
  28960.  
  28961. !DataStream methodsFor: 'all'!
  28962. readFloat
  28963.     "PRIVATE -- Read the contents of a Float.
  28964.      This is the fast way to read a Float.
  28965.      We support 8-byte Floats here.  Non-IEEE"
  28966.  
  28967.     | new |
  28968.     new _ Float new: 2.        "To get an instance"
  28969.     new at: 1 put: (byteStream nextNumber: 4).
  28970.     new at: 2 put: (byteStream nextNumber: 4).
  28971.     ^ new! !
  28972.  
  28973. !DataStream methodsFor: 'all'!
  28974. readFloatString
  28975.     "PRIVATE -- Read the contents of a Float string.
  28976.      This is the slow way to read a Float--via its string rep’n.
  28977.      It's here for compatibility with old data files."
  28978.  
  28979.     ^ Float readFrom: (byteStream next: (byteStream nextNumber: 4))! !
  28980.  
  28981. !DataStream methodsFor: 'all' stamp: 'tk 1/8/97'!
  28982. readInstance
  28983.     "PRIVATE -- Read the contents of an arbitrary instance.
  28984.      ASSUMES: readDataFrom:size: sends me beginReference: after it
  28985.        instantiates the new object but before reading nested objects.
  28986.      NOTE: We must restore the current reference position after
  28987.        recursive calls to next.
  28988.     Let the instance, not the class read the data.  "
  28989.     | instSize aSymbol refPosn anObject newClass |
  28990.  
  28991.     instSize _ (byteStream nextNumber: 4) - 1.
  28992.     refPosn _ self getCurrentReference.
  28993.     aSymbol _ self next.
  28994.     newClass _ Smalltalk at: aSymbol asSymbol.
  28995.     anObject _ newClass isVariable     "Create object here"
  28996.             ifFalse: [newClass basicNew]
  28997.             ifTrue: [newClass basicNew: instSize - (newClass instSize)].
  28998.     self setCurrentReference: refPosn.  "before readDataFrom:size:"
  28999.     anObject _ anObject readDataFrom: self size: instSize.
  29000.     self setCurrentReference: refPosn.  "before returning to next"
  29001.     ^ anObject! !
  29002.  
  29003. !DataStream methodsFor: 'all'!
  29004. readInteger
  29005.     "PRIVATE -- Read the contents of a SmallInteger."
  29006.  
  29007.     ^ byteStream nextInt32    "signed!!!!!!"! !
  29008.  
  29009. !DataStream methodsFor: 'all'!
  29010. readNil
  29011.     "PRIVATE -- Read the contents of an UndefinedObject."
  29012.  
  29013.     ^ nil! !
  29014.  
  29015. !DataStream methodsFor: 'all' stamp: ' 6/9/97'!
  29016. readRectangle
  29017.     "Read a compact Rectangle.  Rectangles with values outside +/- 2047 were stored as normal objects (type=9).  They will not come here.  17:22 tk"
  29018.  
  29019.     "Encoding is four 12-bit signed numbers.  48 bits in next 6 bytes.  17:24 tk"
  29020.     | acc left top right bottom |
  29021.     acc _ byteStream nextNumber: 3.
  29022.     left _ acc bitShift: -12.
  29023.     (left bitAnd: 16r800) ~= 0 ifTrue: [left _ left - 16r1000].    "sign"
  29024.     top _ acc bitAnd: 16rFFF.
  29025.     (top bitAnd: 16r800) ~= 0 ifTrue: [top _ top - 16r1000].    "sign"
  29026.  
  29027.     acc _ byteStream nextNumber: 3.
  29028.     right _ acc bitShift: -12.
  29029.     (right bitAnd: 16r800) ~= 0 ifTrue: [right _ right - 16r1000].    "sign"
  29030.     bottom _ acc bitAnd: 16rFFF.
  29031.     (bottom bitAnd: 16r800) ~= 0 ifTrue: [bottom _ bottom - 16r1000].    "sign"
  29032.     
  29033.     ^ Rectangle left: left right: right top: top bottom: bottom
  29034. ! !
  29035.  
  29036. !DataStream methodsFor: 'all' stamp: ' 6/9/97'!
  29037. readReference
  29038.     "PRIVATE -- Read the contents of an object reference. Cf. outputReference:.
  29039.     11/15/92 jhm: Support weak references.
  29040.     08:09 tk Data on file is relative to base position (where DataStream took over)."
  29041.     | referencePosition |
  29042.  
  29043.     ^ (referencePosition _ (byteStream nextNumber: 4)) = self vacantRef    "relative"
  29044.         ifTrue:  [nil]
  29045.         ifFalse: [self objectAt: referencePosition]        "relative pos"! !
  29046.  
  29047. !DataStream methodsFor: 'all' stamp: 'tk 1/8/97'!
  29048. readShortInst
  29049.     "Read the contents of an arbitrary instance that has a short header.
  29050.      ASSUMES: readDataFrom:size: sends me beginReference: after it
  29051.        instantiates the new object but before reading nested objects.
  29052.      NOTE: We must restore the current reference position after
  29053.        recursive calls to next.
  29054.     Let the instance, not the class read the data.  "
  29055.     | instSize aSymbol refPosn anObject newClass |
  29056.  
  29057.     instSize _ (byteStream next) - 1.    "one byte of size"
  29058.     refPosn _ self getCurrentReference.
  29059.     aSymbol _ self readShortRef.    "class symbol in two bytes of file pos"
  29060.     newClass _ Smalltalk at: aSymbol asSymbol.
  29061.     anObject _ newClass isVariable     "Create object here"
  29062.             ifFalse: [newClass basicNew]
  29063.             ifTrue: [newClass basicNew: instSize - (newClass instSize)].
  29064.     self setCurrentReference: refPosn.  "before readDataFrom:size:"
  29065.     anObject _ anObject readDataFrom: self size: instSize.
  29066.     self setCurrentReference: refPosn.  "before returning to next"
  29067.     ^ anObject! !
  29068.  
  29069. !DataStream methodsFor: 'all' stamp: '6/10/97 17:03 tk'!
  29070. readShortRef
  29071.     "Read an object reference from two bytes only.  Original object must be in first 65536 bytes of the file."
  29072.     | referencePosition |
  29073.  
  29074.     ^ (referencePosition _ (byteStream nextNumber: 2)) = self vacantRef    "relative"
  29075.         ifTrue:  [nil]
  29076.         ifFalse: [self objectAt: referencePosition]        "relative pos"! !
  29077.  
  29078. !DataStream methodsFor: 'all'!
  29079. readString
  29080.     "PRIVATE -- Read the contents of a String."
  29081.  
  29082.     ^ byteStream nextString! !
  29083.  
  29084. !DataStream methodsFor: 'all'!
  29085. readSymbol
  29086.     "PRIVATE -- Read the contents of a Symbol."
  29087.  
  29088.     ^ self readString asSymbol! !
  29089.  
  29090. !DataStream methodsFor: 'all'!
  29091. readTrue
  29092.     "PRIVATE -- Read the contents of a True."
  29093.  
  29094.     ^ true! !
  29095.  
  29096. !DataStream methodsFor: 'all'!
  29097. readUser
  29098.     "Reconstruct both the private class and the instance.  7/29/96 tk"
  29099.     | instSize aSymbol refPosn anObject |
  29100.  
  29101.     anObject _ self readInstance.        "Will create new unique class"
  29102.     ^ anObject! !
  29103.  
  29104. !DataStream methodsFor: 'all'!
  29105. reset
  29106.     "Reset the stream."
  29107.  
  29108.     byteStream reset! !
  29109.  
  29110. !DataStream methodsFor: 'all' stamp: 'tk 5/29/97'!
  29111. rootObject
  29112.     "Return the object at the root of the tree we are filing out.  "
  29113.  
  29114.     ^ topCall! !
  29115.  
  29116. !DataStream methodsFor: 'all' stamp: 'tk 5/29/97'!
  29117. rootObject: anObject
  29118.     "Return the object at the root of the tree we are filing out.  "
  29119.  
  29120.     topCall _ anObject! !
  29121.  
  29122. !DataStream methodsFor: 'all'!
  29123. setCurrentReference: refPosn
  29124.     "PRIVATE -- Set currentReference to refPosn.
  29125.      Noop here. Cf. ReferenceStream."! !
  29126.  
  29127. !DataStream methodsFor: 'all' stamp: '6/9/97 08:03 di'!
  29128. setStream: aStream
  29129.     "PRIVATE -- Initialization method."
  29130.  
  29131.     aStream binary.
  29132.     basePos _ aStream position.    "Remember where we start.  Earlier part of file contains a class or method file-in.  Allow that to be edited.  We don't deal in absolute file locations."
  29133.     byteStream _ aStream.! !
  29134.  
  29135. !DataStream methodsFor: 'all'!
  29136. size
  29137.     "Answer the stream's size."
  29138.  
  29139.     ^ byteStream size! !
  29140.  
  29141. !DataStream methodsFor: 'all'!
  29142. tryToPutReference: anObject typeID: typeID
  29143.     "PRIVATE -- If we support references for type typeID, and if
  29144.        anObject already appears in my output stream, then put a
  29145.        reference to the place where anObject already appears. If we
  29146.        support references for typeID but didn’t already put anObject,
  29147.        then associate the current stream position with anObject in
  29148.        case one wants to nextPut: it again.
  29149.      Return true after putting a reference; false if the object still
  29150.        needs to be put.
  29151.      For DataStream this is trivial. ReferenceStream overrides this."
  29152.  
  29153.     ^ false! !
  29154.  
  29155. !DataStream methodsFor: 'all' stamp: 'tk 3/15/98 12:35'!
  29156. typeIDFor: anObject
  29157.     "Return the typeID for anObject's class.  This is where the tangle of objects is clipped to stop everything from going out.  
  29158.     Classes can control their instance variables by defining objectToStoreOnDataStream.
  29159.     Any object in blockers is not written out.  See ReferenceStream.objectIfBlocked: and DataStream nextPut:.
  29160.     Morphs do not write their owners.  See Morph.storeDataOn:   Each morph tells itself to 'prepareToBeSaved' before writing out."
  29161.     
  29162.     ^ TypeMap at: anObject class ifAbsent: [9 "instance of any normal class"]    
  29163. "See DataStream initialize.  nil=1. true=2. false=3. a SmallInteger=4. a String=5. a Symbol=6.  a ByteArray=7. an Array=8. other = 9.  a Bitmap=11. a Metaclass=12. a Float=14.  a Rectangle=15. any instance that can have a short header=16."! !
  29164.  
  29165. !DataStream methodsFor: 'all' stamp: 'jhm 11/15/92'!
  29166. vacantRef
  29167.     "Answer the magic 32-bit constant we use ***ON DISK*** as a stream 'reference
  29168.      position' to identify a reference that's not yet filled in. This must be a
  29169.      value that won't be used as an ordinary reference. Cf. outputReference: and
  29170.      readReference. -- 
  29171.      NOTE: We could use a different type ID for vacant-refs rather than writing
  29172.         object-references with a magic value. (The type ID and value are
  29173.         overwritten by ordinary object-references when weak refs are fullfilled.)"
  29174.  
  29175.     ^ -1! !
  29176.  
  29177. !DataStream methodsFor: 'all'!
  29178. writeArray: anArray
  29179.     "PRIVATE -- Write the contents of an Array."
  29180.  
  29181.     byteStream nextNumber: 4 put: anArray size.
  29182.     self nextPutAll: anArray.! !
  29183.  
  29184. !DataStream methodsFor: 'all' stamp: 'jm 12/3/97 21:39'!
  29185. writeBitmap: aBitmap
  29186.     "PRIVATE -- Write the contents of a Bitmap."
  29187.  
  29188.     (byteStream isKindOf: DummyStream) ifTrue: [^ self].
  29189.     aBitmap writeOn: byteStream
  29190.     "Note that this calls (byteStream nextPutAll: aBitmap) which knows enough to put 4-byte quantities on the stream!!  Reader must know that size is in long words."! !
  29191.  
  29192. !DataStream methodsFor: 'all'!
  29193. writeBoolean: aBoolean
  29194.     "PRIVATE -- Write the contents of a Boolean.
  29195.      This method is now obsolete."
  29196.  
  29197.     byteStream nextPut: (aBoolean ifTrue: [1] ifFalse: [0])! !
  29198.  
  29199. !DataStream methodsFor: 'all' stamp: 'jm 12/3/97 20:45'!
  29200. writeByteArray: aByteArray
  29201.     "PRIVATE -- Write the contents of a ByteArray."
  29202.  
  29203.     (byteStream isKindOf: DummyStream) ifTrue: [^ self].
  29204.     byteStream nextNumber: 4 put: aByteArray size.
  29205.     "May have to convert types here..."
  29206.     byteStream nextPutAll: aByteArray.! !
  29207.  
  29208. !DataStream methodsFor: 'all' stamp: 'tk 3/24/98 10:27'!
  29209. writeClass: aClass
  29210.     "Write out a DiskProxy for the class.  It will look up the class's name in Smalltalk in the new sustem.  Never write classes or methodDictionaries as objects.  For novel classes, front part of file is a fileIn of the new class."
  29211.  
  29212.     "This method never executed because objectToStoreOnDataStream returns a DiskProxy.  See DataStream.nextPut:"
  29213.     ^ self error: 'Write a DiskProxy instead'! !
  29214.  
  29215. !DataStream methodsFor: 'all'!
  29216. writeFalse: aFalse
  29217.     "PRIVATE -- Write the contents of a False."! !
  29218.  
  29219. !DataStream methodsFor: 'all'!
  29220. writeFloat: aFloat
  29221.     "PRIVATE -- Write the contents of a Float.
  29222.       We support 8-byte Floats here."
  29223.  
  29224.     byteStream nextNumber: 4 put: (aFloat at: 1).
  29225.     byteStream nextNumber: 4 put: (aFloat at: 2).
  29226. ! !
  29227.  
  29228. !DataStream methodsFor: 'all'!
  29229. writeFloatString: aFloat
  29230.     "PRIVATE -- Write the contents of a Float string.
  29231.      This is the slow way to write a Float--via its string rep’n."
  29232.  
  29233.     self writeByteArray: (aFloat printString)! !
  29234.  
  29235. !DataStream methodsFor: 'all'!
  29236. writeInstance: anObject
  29237.     "PRIVATE -- Write the contents of an arbitrary instance."
  29238.  
  29239.     ^ anObject storeDataOn: self! !
  29240.  
  29241. !DataStream methodsFor: 'all'!
  29242. writeInteger: anInteger
  29243.     "PRIVATE -- Write the contents of a SmallInteger."
  29244.  
  29245.     byteStream nextInt32Put: anInteger    "signed!!!!!!!!!!"! !
  29246.  
  29247. !DataStream methodsFor: 'all'!
  29248. writeNil: anUndefinedObject
  29249.     "PRIVATE -- Write the contents of an UndefinedObject."! !
  29250.  
  29251. !DataStream methodsFor: 'all' stamp: 'jm 7/31/97 16:16'!
  29252. writeRectangle: anObject
  29253.     "Write the contents of a Rectangle.  See if it can be a compact Rectangle (type=15).  Rectangles with values outside +/- 2047 were stored as normal objects (type=9).  17:22 tk"
  29254.  
  29255.     | ok right bottom top left acc |
  29256.     ok _ true.
  29257.     (right _ anObject right) > 2047 ifTrue: [ok _ false].
  29258.     right < -2048 ifTrue: [ok _ false].
  29259.     (bottom _ anObject bottom) > 2047 ifTrue: [ok _ false].
  29260.     bottom < -2048 ifTrue: [ok _ false].
  29261.     (top _ anObject top) > 2047 ifTrue: [ok _ false].
  29262.     top < -2048 ifTrue: [ok _ false].
  29263.     (left _ anObject left) > 2047 ifTrue: [ok _ false].
  29264.     left < -2048 ifTrue: [ok _ false].
  29265.     ok _ ok & left isInteger & right isInteger & top isInteger & bottom isInteger.
  29266.  
  29267.     ok ifFalse: [
  29268.         byteStream skip: -1; nextPut: 9; skip: 0. "rewrite type to be normal instance"
  29269.         ^ anObject storeDataOn: self].
  29270.  
  29271.     acc _ ((left bitAnd: 16rFFF) bitShift: 12) + (top bitAnd: 16rFFF).
  29272.     byteStream nextNumber: 3 put: acc.
  29273.     acc _ ((right bitAnd: 16rFFF) bitShift: 12) + (bottom bitAnd: 16rFFF).
  29274.     byteStream nextNumber: 3 put: acc.! !
  29275.  
  29276. !DataStream methodsFor: 'all' stamp: 'jm 12/3/97 20:45'!
  29277. writeString: aString
  29278.     "PRIVATE -- Write the contents of a String."
  29279.  
  29280.     (byteStream isKindOf: DummyStream) ifTrue: [^ self].
  29281.     aString size < 16384 
  29282.         ifTrue: [byteStream nextStringPut: aString]
  29283.         ifFalse: [self writeByteArray: aString].    "takes more space"! !
  29284.  
  29285. !DataStream methodsFor: 'all'!
  29286. writeSymbol: aSymbol
  29287.     "PRIVATE -- Write the contents of a Symbol."
  29288.  
  29289.     self writeString: aSymbol! !
  29290.  
  29291. !DataStream methodsFor: 'all'!
  29292. writeTrue: aTrue
  29293.     "PRIVATE -- Write the contents of a True."! !
  29294.  
  29295. !DataStream methodsFor: 'all'!
  29296. writeUser: anObject
  29297.     "Write the contents of an arbitrary User instance (and its devoted class)."
  29298.     " 7/29/96 tk"
  29299.  
  29300.     "If anObject is an instance of a unique user class, will lie and say it has a generic class"
  29301.     ^ anObject storeDataOn: self! !
  29302.  
  29303. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29304.  
  29305. DataStream class
  29306.     instanceVariableNames: ''!
  29307.  
  29308. !DataStream class methodsFor: 'all'!
  29309. example
  29310.     "An example and test of DataStream/ReferenceStream.
  29311.      11/19/92 jhm: Use self testWith:."
  29312.     "DataStream example"
  29313.     "ReferenceStream example"
  29314.     | input sharedPoint |
  29315.  
  29316.     "Construct the test data."
  29317.     input _ Array new: 9.
  29318.     input at: 1 put: nil.
  29319.     input at: 2 put: true.
  29320.     input at: 3 put: (Form extent: 63 @ 50 depth: 8).
  29321.         (input at: 3) fillWithColor: Color lightBlue.
  29322.     input at: 4 put: #(3 3.0 'three').
  29323.     input at: 5 put: false.
  29324.     input at: 6 put: 1024 @ -2048.
  29325.     input at: 7 put: #x.
  29326.     input at: 8 put: (Array with: (sharedPoint _ 0 @ -30000)).
  29327.     input at: 9 put: sharedPoint.
  29328.  
  29329.     "Write it out, read it back, and return it for inspection."
  29330.     ^ self testWith: input! !
  29331.  
  29332. !DataStream class methodsFor: 'all'!
  29333. exampleWithPictures
  29334.     "DataStream exampleWithPictures"
  29335.     | file result |
  29336.     file _ FileStream fileNamed: 'Test-Picture'.
  29337.     file binary.
  29338.     (DataStream on: file) nextPut: (Form fromUser).
  29339.     file close.
  29340.  
  29341.     file _ FileStream fileNamed: 'Test-Picture'.
  29342.     file binary.
  29343.     result _ (DataStream on: file) next.
  29344.     file close.
  29345.     result display.
  29346.     ^ result! !
  29347.  
  29348. !DataStream class methodsFor: 'all'!
  29349. fileNamed: aString
  29350.     "Here is the way to use DataStream and ReferenceStream:
  29351. rr _ ReferenceStream fileNamed: 'test.obj'.
  29352. rr nextPut: <your object>.
  29353. rr close.
  29354. "
  29355.  
  29356.     | strm |
  29357.     strm _ self on: (FileStream fileNamed: aString).        "will be binary"
  29358.     strm byteStream setFileTypeToObject.
  29359.         "Type and Creator not to be text, so can attach correctly to an email msg"
  29360.     ^ strm! !
  29361.  
  29362. !DataStream class methodsFor: 'all' stamp: '6/10/97 16:51 tk'!
  29363. initialize
  29364.     "TypeMap maps Smalltalk classes to type ID numbers which identify the data stream primitive formats.  nextPut: writes these IDs to the data stream.  NOTE: Changing these type ID numbers will invalidate all extant data stream files.  Adding new ones is OK.
  29365.      See nextPut:, next, typeIDFor:, & ReferenceStream>>isAReferenceType:"
  29366.     "DataStream initialize"
  29367.  
  29368.     | refTypes t |
  29369.     refTypes _ OrderedCollection new.
  29370.     t _ TypeMap _ Dictionary new: 30. "sparse for fast hashing"
  29371.  
  29372.     t at: UndefinedObject put: 1.   refTypes add: 0.
  29373.     t at: True put: 2.   refTypes add: 0.
  29374.     t at: False put: 3.   refTypes add: 0.
  29375.     t at: SmallInteger put: 4.     refTypes add: 0.
  29376.     t at: String put: 5.   refTypes add: 1.
  29377.     t at: Symbol put: 6.   refTypes add: 1.
  29378.     t at: ByteArray put: 7.   refTypes add: 1.
  29379.         "Does anything use this?"
  29380.     t at: Array put: 8.   refTypes add: 1.
  29381.     "(type ID 9 is for arbitrary instances, cf. typeIDFor:)"
  29382.         refTypes add: 1.
  29383.     "(type ID 10 is for references, cf. ReferenceStream>>tryToPutReference:)"
  29384.         refTypes add: 0.
  29385.     t at: Bitmap put: 11.   refTypes add: 1.
  29386.     t at: Metaclass put: 12.   refTypes add: 0.
  29387.     "Type ID 13 is used for HyperSqueak User classes that must be reconstructed."
  29388.         refTypes add: 1.
  29389.     t at: Float put: 14.  refTypes add: 1.
  29390.     t at: Rectangle put: 15.  refTypes add: 1.    "Allow compact Rects."
  29391.     "type ID 16 is an instance with short header.  See beginInstance:size:"
  29392.         refTypes add: 1.
  29393.     "t at:  put: 17.  refTypes add: 0."
  29394.     ReferenceStream refTypes: refTypes.    "save it"! !
  29395.  
  29396. !DataStream class methodsFor: 'all' stamp: 'di 2/15/98 14:03'!
  29397. new
  29398.     ^ self basicNew! !
  29399.  
  29400. !DataStream class methodsFor: 'all'!
  29401. newFileNamed: aString
  29402.     "Here is the way to use DataStream and ReferenceStream:
  29403. rr _ ReferenceStream fileNamed: 'test.obj'.
  29404. rr nextPut: <your object>.
  29405. rr close.
  29406. "
  29407.  
  29408.     | strm |
  29409.     strm _  self on: (FileStream newFileNamed: aString).        "will be binary"
  29410.     strm byteStream setFileTypeToObject.
  29411.         "Type and Creator not to be text, so can attach correctly to an email msg"
  29412.     ^ strm! !
  29413.  
  29414. !DataStream class methodsFor: 'all'!
  29415. oldFileNamed: aString
  29416.     "Here is the way to use DataStream and ReferenceStream:
  29417. rr _ ReferenceStream oldFileNamed: 'test.obj'.
  29418. ^ rr nextAndClose.
  29419. "
  29420.  
  29421.     | strm ff |
  29422.     ff _ FileStream oldFileOrNoneNamed: aString.
  29423.     ff ifNil: [^ nil].
  29424.     strm _ self on: (ff binary).
  29425.     ^ strm! !
  29426.  
  29427. !DataStream class methodsFor: 'all' stamp: 'di 6/24/97 00:18'!
  29428. on: aStream
  29429.     "Open a new DataStream onto a low-level I/O stream."
  29430.  
  29431.     ^ self basicNew setStream: aStream
  29432.         "aStream binary is in setStream:"
  29433. ! !
  29434.  
  29435. !DataStream class methodsFor: 'all' stamp: 'jm 12/3/97 19:36'!
  29436. testWith: anObject
  29437.     "As a test of DataStream/ReferenceStream, write out anObject and read it back.
  29438.     11/19/92 jhm: Set the file type. More informative file name."
  29439.     "DataStream testWith: 'hi'"
  29440.     "ReferenceStream testWith: 'hi'"
  29441.     | file result |
  29442.  
  29443.     file _ FileStream fileNamed: (self name, ' test').
  29444.     file binary.
  29445.     (self on: file) nextPut: anObject.
  29446.     file close.
  29447.  
  29448.     file _ FileStream fileNamed: (self name, ' test').
  29449.     file binary.
  29450.     result _ (self on: file) next.
  29451.     file close.
  29452.     ^ result! !
  29453. Magnitude subclass: #Date
  29454.     instanceVariableNames: 'day year '
  29455.     classVariableNames: 'DaysInMonth FirstDayOfMonth MonthNames SecondsInDay WeekDayNames '
  29456.     poolDictionaries: ''
  29457.     category: 'Numeric-Magnitudes'!
  29458. !Date commentStamp: 'di 5/22/1998 16:33' prior: 0!
  29459. Date comment:
  29460. 'I represent a date. My printing format consists of an array of six elements.
  29461.     
  29462. The first three elements contain the numbers 1, 2, 3, in any order. 1 indicates that the day appears in this position, 2 indicates that the month appears in this position, and 3 indicates that the year appears in this position.
  29463.     
  29464. The fourth element is the ascii value of the character separator or the character itself.
  29465.     
  29466. The fifth element is the month format, where 1 indicates print as a number, 2 indicates print the first three characters, and 3 indicates print the entire name.
  29467.     
  29468. The six element is the year format, where 1 indicates print as a number, and 2 indicates print the number modulo 100.
  29469.     
  29470. Examples:
  29471.     #(1 2 3 32 2 1) prints as 12 Dec 1981
  29472.     #(2 1 3 $/ 1 2) prints as 12/12/81'!
  29473.  
  29474.  
  29475. !Date methodsFor: 'accessing'!
  29476. day
  29477.     "Answer the day of the year represented by the receiver."
  29478.  
  29479.     ^day! !
  29480.  
  29481. !Date methodsFor: 'accessing'!
  29482. leap
  29483.     "Answer whether the receiver's year is a leap year."
  29484.  
  29485.     ^Date leapYear: year! !
  29486.  
  29487. !Date methodsFor: 'accessing'!
  29488. monthIndex
  29489.     "Answer the index of the month in which the receiver falls."
  29490.  
  29491.     | leap firstDay |
  29492.     leap _ self leap.
  29493.     12 to: 1 by: -1 do: 
  29494.         [ :monthIndex | 
  29495.             firstDay _ (FirstDayOfMonth at: monthIndex)
  29496.                             + (monthIndex > 2 ifTrue: [leap] ifFalse: [0]).
  29497.             firstDay<= day
  29498.                 ifTrue: [^monthIndex]].
  29499.     self error: 'illegal month'! !
  29500.  
  29501. !Date methodsFor: 'accessing'!
  29502. monthName
  29503.     "Answer the name of the month in which the receiver falls."
  29504.  
  29505.     ^MonthNames at: self monthIndex! !
  29506.  
  29507. !Date methodsFor: 'accessing'!
  29508. weekday
  29509.     "Answer the name of the day of the week on which the receiver falls."
  29510.  
  29511.     ^WeekDayNames at: self weekdayIndex! !
  29512.  
  29513. !Date methodsFor: 'accessing'!
  29514. year
  29515.     "Answer the year in which the receiver falls."
  29516.  
  29517.     ^year! !
  29518.  
  29519.  
  29520. !Date methodsFor: 'arithmetic'!
  29521. addDays: dayCount 
  29522.     "Answer a Date that is dayCount days after the receiver."
  29523.  
  29524.     ^Date newDay: day + dayCount
  29525.           year: year! !
  29526.  
  29527. !Date methodsFor: 'arithmetic'!
  29528. subtractDate: aDate 
  29529.     "Answer the number of days between the receiver and aDate."
  29530.  
  29531.     year = aDate year
  29532.         ifTrue: [^day - aDate day]
  29533.         ifFalse: [^year - 1 // 4 - (aDate year // 4) + day 
  29534.                         + aDate daysLeftInYear + (year - 1 - aDate year * 365)]! !
  29535.  
  29536. !Date methodsFor: 'arithmetic'!
  29537. subtractDays: dayCount 
  29538.     "Answer a Date that is dayCount days before the receiver."
  29539.  
  29540.     ^Date newDay: day - dayCount year: year! !
  29541.  
  29542.  
  29543. !Date methodsFor: 'comparing'!
  29544. < aDate 
  29545.     "Answer whether aDate precedes the date of the receiver." 
  29546.  
  29547.     year = aDate year
  29548.         ifTrue: [^day < aDate day]
  29549.         ifFalse: [^year < aDate year]! !
  29550.  
  29551. !Date methodsFor: 'comparing'!
  29552. = aDate 
  29553.     "Answer whether aDate is the same day as the receiver."
  29554.  
  29555.     self species = aDate species
  29556.         ifTrue: [^day = aDate day & (year = aDate year)]
  29557.         ifFalse: [^false]! !
  29558.  
  29559. !Date methodsFor: 'comparing'!
  29560. hash
  29561.     "Hash is reimplemented because = is implemented."
  29562.  
  29563.     ^(year hash bitShift: 3) bitXor: day! !
  29564.  
  29565.  
  29566. !Date methodsFor: 'inquiries'!
  29567. dayOfMonth
  29568.     "Answer which day of the month is represented by the receiver."
  29569.  
  29570.     ^day - (self firstDayOfMonthIndex: self monthIndex) + 1! !
  29571.  
  29572. !Date methodsFor: 'inquiries'!
  29573. daysInMonth
  29574.     "Answer the number of days in the month represented by the receiver."
  29575.  
  29576.     ^(DaysInMonth at: self monthIndex)
  29577.         + (self monthIndex = 2
  29578.                 ifTrue: [self leap]
  29579.                 ifFalse: [0])! !
  29580.  
  29581. !Date methodsFor: 'inquiries'!
  29582. daysInYear
  29583.     "Answer the number of days in the year represented by the receiver."
  29584.  
  29585.     ^Date daysInYear: self year! !
  29586.  
  29587. !Date methodsFor: 'inquiries'!
  29588. daysLeftInYear
  29589.     "Answer the number of days in the year after the date of the receiver."
  29590.  
  29591.     ^self daysInYear - self day! !
  29592.  
  29593. !Date methodsFor: 'inquiries'!
  29594. firstDayOfMonth
  29595.     "Answer the index of the day of the year that is the first day of the 
  29596.     receiver's month."
  29597.  
  29598.     ^self firstDayOfMonthIndex: self monthIndex! !
  29599.  
  29600. !Date methodsFor: 'inquiries'!
  29601. previous: dayName 
  29602.     "Answer the previous date whose weekday name is dayName."
  29603.  
  29604.     ^self subtractDays: 7 + self weekdayIndex - (Date dayOfWeek: dayName) \\ 7! !
  29605.  
  29606.  
  29607. !Date methodsFor: 'converting'!
  29608. asSeconds
  29609.     "Answer the seconds between a time on 1 January 1901 and the same 
  29610.     time in the receiver's day."
  29611.  
  29612.     ^SecondsInDay * (self subtractDate: (Date newDay: 1 year: 1901))! !
  29613.  
  29614.  
  29615. !Date methodsFor: 'printing' stamp: 'tk 4/10/1998 09:20'!
  29616. mmddyy
  29617.     "Please use mmddyyyy instead, so dates in 2000 will be unambiguous"
  29618.     "Answer the receiver rendered in standard fmt mm/dd/yy. 1/17/96 sw.  2/1/96 sw Fixed to show day of month, not day.  Note that the name here is slightly misleading -- the month and day numbers don't show leading zeros, so that for example feb 1 1996 is 2/1/96"
  29619.  
  29620.     "Date today mmddyy"
  29621.  
  29622.     ^ self printFormat: #(2 1 3 $/ 1 2)! !
  29623.  
  29624. !Date methodsFor: 'printing' stamp: 'tk 1/27/98 08:30'!
  29625. mmddyyyy
  29626.     "Answer the receiver rendered in standard fmt mm/dd/yyyy.  Good for avoiding year 2000 bugs.  Note that the name here is slightly misleading -- the month and day numbers don't show leading zeros, so that for example feb 1 1996 is 2/1/96"
  29627.  
  29628.     "Date today mmddyyyy"
  29629.  
  29630.     ^ self printFormat: #(2 1 3 $/ 1 1)! !
  29631.  
  29632. !Date methodsFor: 'printing'!
  29633. printFormat: formatArray 
  29634.     "Answer a String describing the receiver using the format denoted by the 
  29635.     argument, formatArray."
  29636.  
  29637.     | aStream |
  29638.     aStream _ WriteStream on: (String new: 16).
  29639.     self printOn: aStream format: formatArray.
  29640.     ^aStream contents! !
  29641.  
  29642. !Date methodsFor: 'printing'!
  29643. printOn: aStream
  29644.  
  29645.     self printOn: aStream format: #(1 2 3 $  3 1 )! !
  29646.  
  29647. !Date methodsFor: 'printing'!
  29648. printOn: aStream format: formatArray 
  29649.     "Print a description of the receiver on aStream using the format denoted 
  29650.     by the argument, formatArray:
  29651.         #(item item item sep monthfmt yearfmt twoDigits)
  29652.         items:  1=day  2=month  3=year  will appear in the order given,
  29653.         separated by sep which is eaither an ascii code or character.
  29654.         monthFmt:  1=09  2=Sep  3=September
  29655.         yearFmt:  1=1996  2=96
  29656.         digits:  (missing or)1=9  2=09.
  29657.     See the examples in printOn: and mmddyy"
  29658.     | monthIndex element monthFormat twoDigits monthDay |
  29659.     twoDigits _ formatArray size > 6 and: [(formatArray at: 7) > 1].
  29660.     monthIndex _ self monthIndex.
  29661.     1 to: 3 do: 
  29662.         [:elementIndex | 
  29663.         element _ formatArray at: elementIndex.
  29664.         element = 1 ifTrue:
  29665.             [monthDay _ day - self firstDayOfMonth + 1.
  29666.             twoDigits & (monthDay < 10) ifTrue: [aStream nextPutAll: '0'].
  29667.                 monthDay printOn: aStream].
  29668.         element = 2 ifTrue: 
  29669.             [monthFormat _ formatArray at: 5.
  29670.             monthFormat = 1 ifTrue:
  29671.                 [twoDigits & (monthIndex < 10) ifTrue: [aStream nextPutAll: '0'].
  29672.                 monthIndex printOn: aStream].
  29673.             monthFormat = 2 ifTrue:
  29674.                 [aStream nextPutAll: ((MonthNames at: monthIndex)
  29675.                                                 copyFrom: 1 to: 3)].
  29676.             monthFormat = 3 ifTrue:
  29677.                 [aStream nextPutAll: (MonthNames at: monthIndex)]].
  29678.         element = 3 ifTrue: 
  29679.             [(formatArray at: 6) = 1
  29680.                 ifTrue: [year printOn: aStream]
  29681.                 ifFalse: [twoDigits & ((year \\ 100) < 10)
  29682.                             ifTrue: [aStream nextPutAll: '0'].
  29683.                         (year \\ 100) printOn: aStream]].
  29684.         elementIndex < 3 ifTrue: 
  29685.             [(formatArray at: 4) ~= 0 
  29686.                 ifTrue: [aStream nextPut: (formatArray at: 4) asCharacter]]]! !
  29687.  
  29688. !Date methodsFor: 'printing'!
  29689. storeOn: aStream
  29690.  
  29691.     aStream nextPutAll: '(', self class name, ' readFromString: ';
  29692.         print: self printString;
  29693.         nextPut: $)! !
  29694.  
  29695.  
  29696. !Date methodsFor: 'private'!
  29697. day: dayInteger year: yearInteger
  29698.  
  29699.     day _ dayInteger.
  29700.     year _ yearInteger! !
  29701.  
  29702. !Date methodsFor: 'private'!
  29703. firstDayOfMonthIndex: monthIndex 
  29704.     "Answer the day of the year (an Integer) that is the first day of my month"
  29705.  
  29706.     ^(FirstDayOfMonth at: monthIndex)
  29707.         + (monthIndex > 2
  29708.                 ifTrue: [self leap]
  29709.                 ifFalse: [0])! !
  29710.  
  29711. !Date methodsFor: 'private' stamp: 'jm 1/6/98 13:38'!
  29712. weekdayIndex
  29713.     "Monday=1, ... , Sunday=7"
  29714.  
  29715.     | yearIndex dayIndex |  
  29716.     day < (self firstDayOfMonthIndex: 3)
  29717.         ifTrue: 
  29718.             [yearIndex _ year - 1.
  29719.             dayIndex _ 307]
  29720.         ifFalse: 
  29721.             [yearIndex _ year.
  29722.             dayIndex _ -58 - self leap].  
  29723.     
  29724.     ^dayIndex + day + yearIndex + (yearIndex // 4) 
  29725.                 + (yearIndex // 400) - (yearIndex // 100) \\ 7 + 1! !
  29726.  
  29727. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  29728.  
  29729. Date class
  29730.     instanceVariableNames: ''!
  29731.  
  29732. !Date class methodsFor: 'class initialization'!
  29733. initialize
  29734.     "Initialize class variables representing the names of the months and days and
  29735.     the number of seconds, days in each month, and first day of each month."
  29736.  
  29737.     MonthNames _ 
  29738.         #(January February March April May June 
  29739.             July August September October November December ).
  29740.     SecondsInDay _ 24 * 60 * 60.
  29741.     DaysInMonth _ #(31 28 31 30 31 30 31 31 30 31 30 31 ).
  29742.     FirstDayOfMonth _ #(1 32 60 91 121 152 182 213 244 274 305 335 ).
  29743.     WeekDayNames _ 
  29744.         #(Monday Tuesday Wednesday Thursday Friday Saturday Sunday )
  29745.  
  29746.     "Date initialize."
  29747. ! !
  29748.  
  29749.  
  29750. !Date class methodsFor: 'instance creation'!
  29751. fromDays: dayCount
  29752.     "Answer an instance of me which is dayCount days after January 1, 
  29753.     1901."
  29754.  
  29755.     ^self
  29756.         newDay: 1 + (dayCount asInteger rem: 1461)
  29757.                             "There are 1461 days in a 4-year cycle. 
  29758.                              2000 is a leap year, so no extra correction is necessary. "
  29759.         year: 1901 + ((dayCount asInteger quo: 1461) * 4)! !
  29760.  
  29761. !Date class methodsFor: 'instance creation'!
  29762. fromString: aString
  29763.     "Answer an instance of created from a string with format DD.MM.YYYY."
  29764.  
  29765.     | fields |
  29766.     fields := aString findTokens: './'.
  29767.     ^self newDay: (fields at: 1) asNumber month: (fields at: 2) asNumber year: (fields at: 3) asNumber! !
  29768.  
  29769. !Date class methodsFor: 'instance creation' stamp: 'tk 4/10/1998 06:40'!
  29770. newDay: day month: monthName year: year 
  29771.     "Answer an instance of me which is the day'th day of the month named 
  29772.      monthName in the year'th year. The year may be specified as the actual 
  29773.      number of years since the beginning of the Roman calendar or the 
  29774.      number of years since 1900.  **Note** two digit dates are always from 1900.
  29775.         1/1/01 will NOT mean 2001."
  29776.     "Tolerate a month index instead of a month name."
  29777.  
  29778.     | monthIndex daysInMonth firstDayOfMonth |
  29779.     year < 100 ifTrue: [^ self
  29780.             newDay: day
  29781.             month: monthName
  29782.             year: 1900 + year].
  29783.     monthIndex _ monthName isInteger
  29784.      ifTrue: [monthName] ifFalse: [self indexOfMonth: monthName].
  29785.     monthIndex = 2
  29786.         ifTrue: [daysInMonth _ (DaysInMonth at: monthIndex)
  29787.                         + (self leapYear: year)]
  29788.         ifFalse: [daysInMonth _ DaysInMonth at: monthIndex].
  29789.     monthIndex > 2
  29790.         ifTrue: [firstDayOfMonth _ (FirstDayOfMonth at: monthIndex)
  29791.                         + (self leapYear: year)]
  29792.         ifFalse: [firstDayOfMonth _ FirstDayOfMonth at: monthIndex].
  29793.     (day < 1 or: [day > daysInMonth])
  29794.         ifTrue: [self error: 'illegal day in month']
  29795.         ifFalse: [^self new day: day - 1 + firstDayOfMonth year: year]! !
  29796.  
  29797. !Date class methodsFor: 'instance creation'!
  29798. newDay: dayCount year: referenceYear 
  29799.     "Answer an instance of me which is dayCount days after the beginning 
  29800.     of the year referenceYear."
  29801.  
  29802.     | day year daysInYear |
  29803.     day _ dayCount.
  29804.     year _ referenceYear.
  29805.     [day > (daysInYear _ self daysInYear: year)]
  29806.         whileTrue: 
  29807.             [year _ year + 1.
  29808.              day _ day - daysInYear].
  29809.     [day <= 0]
  29810.         whileTrue: 
  29811.             [year _ year - 1.
  29812.              day _ day + (self daysInYear: year)].
  29813.     ^self new day: day year: year! !
  29814.  
  29815. !Date class methodsFor: 'instance creation'!
  29816. readFrom: aStream
  29817.     "Read a Date from the stream in any of the forms:
  29818.         <day> <monthName> <year>        (5 April 1982; 5-APR-82)
  29819.         <monthName> <day> <year>        (April 5, 1982)
  29820.         <monthNumber> <day> <year>    (4/5/82)"
  29821.  
  29822.     | day month |
  29823.     aStream peek isDigit ifTrue: [day _ Integer readFrom: aStream].
  29824.     [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1].
  29825.     aStream peek isLetter
  29826.         ifTrue:        "number/name... or name..."
  29827.             [month _ WriteStream on: (String new: 10).
  29828.             [aStream peek isLetter] whileTrue: [month nextPut: aStream next].
  29829.             month _ month contents.
  29830.             day isNil ifTrue:        "name/number..."
  29831.                 [[aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1].
  29832.                 day _ Integer readFrom: aStream]]
  29833.         ifFalse:        "number/number..."
  29834.             [month _ Date nameOfMonth: day.
  29835.             day _ Integer readFrom: aStream].
  29836.     [aStream peek isAlphaNumeric] whileFalse: [aStream skip: 1].
  29837.     ^self newDay: day month: month year: (Integer readFrom: aStream)
  29838.  
  29839.     "Date readFrom: (ReadStream on: '5APR82')"
  29840. ! !
  29841.  
  29842. !Date class methodsFor: 'instance creation'!
  29843. today
  29844.     "Answer an instance of me representing the day and year right now."
  29845.  
  29846.     ^self dateAndTimeNow at: 1! !
  29847.  
  29848.  
  29849. !Date class methodsFor: 'general inquiries'!
  29850. dateAndTimeNow
  29851.     "Answer an Array whose first element is Date today and second element 
  29852.     is Time now."
  29853.  
  29854.     ^Time dateAndTimeNow! !
  29855.  
  29856. !Date class methodsFor: 'general inquiries'!
  29857. dayOfWeek: dayName 
  29858.     "Answer the index in a week, 1-7, of the day named dayName. Create an 
  29859.     error notification if no such day exists."
  29860.  
  29861.     1 to: 7 do: [:index | (WeekDayNames at: index)
  29862.             = dayName ifTrue: [^index]].
  29863.     self error: dayName asString , ' is not a day of the week'! !
  29864.  
  29865. !Date class methodsFor: 'general inquiries'!
  29866. daysInMonth: monthName forYear: yearInteger 
  29867.     "Answer the number of days in the month named monthName in the 
  29868.     year yearInteger."
  29869.  
  29870.     ^(self newDay: 1
  29871.           month: monthName
  29872.           year: yearInteger) daysInMonth! !
  29873.  
  29874. !Date class methodsFor: 'general inquiries'!
  29875. daysInYear: yearInteger 
  29876.     "Answer the number of days in the year, yearInteger."
  29877.  
  29878.     ^365 + (self leapYear: yearInteger)! !
  29879.  
  29880. !Date class methodsFor: 'general inquiries'!
  29881. firstWeekdayOfMonth: mn year: yr
  29882.     "Answer the weekday index (Sunday=1, etc) of the first day in the month named mn in the year yr."
  29883.  
  29884.     ^(self newDay: 1 month: mn year: yr) weekdayIndex + 7 \\ 7 + 1! !
  29885.  
  29886. !Date class methodsFor: 'general inquiries'!
  29887. indexOfMonth: monthName 
  29888.     "Answer the index, 1-12, of the month monthName. Create an error 
  29889.     notification if no such month exists."
  29890.  
  29891.     1 to: 12 do: 
  29892.         [ :index | 
  29893.             (monthName , '*' match: (MonthNames at: index))
  29894.                         ifTrue: [^index]].
  29895.     self error: monthName , ' is not a recognized month name'! !
  29896.  
  29897. !Date class methodsFor: 'general inquiries'!
  29898. leapYear: yearInteger 
  29899.     "Answer 1 if the year yearInteger is a leap year; answer 0 if it is not."
  29900.  
  29901.     (yearInteger \\ 4 ~= 0 or: [yearInteger \\ 100 = 0 and: [yearInteger \\ 400 ~= 0]])
  29902.         ifTrue: [^0]
  29903.         ifFalse: [^1]! !
  29904.  
  29905. !Date class methodsFor: 'general inquiries'!
  29906. nameOfDay: dayIndex 
  29907.     "Answer a symbol representing the name of the day indexed by 
  29908.     dayIndex, 1-7."
  29909.  
  29910.     ^WeekDayNames at: dayIndex! !
  29911.  
  29912. !Date class methodsFor: 'general inquiries'!
  29913. nameOfMonth: monthIndex 
  29914.     "Answer a String representing the name of the month indexed by 
  29915.     monthIndex, 1-12."
  29916.  
  29917.     ^MonthNames at: monthIndex! !
  29918. StringHolder subclass: #Debugger
  29919.     instanceVariableNames: 'interruptedProcess interruptedController contextStack contextStackTop contextStackIndex contextStackList receiverInspector contextVariablesInspector externalInterrupt proceedValue selectingPC sourceMap tempNames '
  29920.     classVariableNames: 'ContextStackKeystrokes ErrorRecursion '
  29921.     poolDictionaries: ''
  29922.     category: 'Interface-Debugger'!
  29923. !Debugger commentStamp: 'di 5/22/1998 16:33' prior: 0!
  29924. Debugger comment:
  29925. 'I represent the machine state at the time of an interrupted process. I also represent a query path into the state of the process. As a StringHolder, the string to be viewed is the interrupted method at some point in the sequence of message-sends that have been initiated but not completed.'!
  29926.  
  29927.  
  29928. !Debugger methodsFor: 'initialize' stamp: 'tm 5/10/1998 15:08'!
  29929. buildMVCDebuggerViewLabel: aString minSize: aPoint
  29930.  
  29931.     | topView stackListView stackCodeView rcvrVarView rcvrValView ctxtVarView ctxtValView |
  29932.     self expandStack.
  29933.     topView _ StandardSystemView new model: self.
  29934.     topView borderWidth: 1.
  29935.     stackListView _ PluggableListView on: self
  29936.             list: #contextStackList
  29937.             selected: #contextStackIndex
  29938.             changeSelected: #toggleContextStackIndex:
  29939.             menu: #contextStackMenu:shifted:
  29940.             keystroke: #contextStackKey:from:.
  29941.         stackListView window: (0 @ 0 extent: 150 @ 50).
  29942.         topView addSubView: stackListView.
  29943.     stackCodeView _ PluggableTextView on: self
  29944.             text: #contents accept: #contents:notifying:
  29945.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  29946.         stackCodeView window: (0 @ 0 extent: 150 @ 75).
  29947.         topView addSubView: stackCodeView below: stackListView.
  29948.     rcvrVarView _ PluggableListView on: self receiverInspector
  29949.             list: #fieldList
  29950.             selected: #selectionIndex
  29951.             changeSelected: #toggleIndex:
  29952.             menu: #fieldListMenu:
  29953.             keystroke: #inspectorKey:from:.
  29954.         rcvrVarView window: (0 @ 0 extent: 25 @ 50).
  29955.         topView addSubView: rcvrVarView below: stackCodeView.
  29956.     rcvrValView _ PluggableTextView on: self receiverInspector
  29957.             text: #contents accept: #accept:
  29958.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  29959.         rcvrValView window: (0 @ 0 extent: 50 @ 50).
  29960.         topView addSubView: rcvrValView toRightOf: rcvrVarView.
  29961.     ctxtVarView _ PluggableListView on: self contextVariablesInspector
  29962.             list: #fieldList
  29963.             selected: #selectionIndex
  29964.             changeSelected: #toggleIndex:
  29965.             menu: #fieldListMenu:
  29966.             keystroke: #inspectorKey:from:.
  29967.         ctxtVarView window: (0 @ 0 extent: 25 @ 50).
  29968.         topView addSubView: ctxtVarView toRightOf: rcvrValView.
  29969.     ctxtValView _ PluggableTextView on: self contextVariablesInspector
  29970.             text: #contents accept: #accept:
  29971.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
  29972.         ctxtValView window: (0 @ 0 extent: 50 @ 50).
  29973.         topView addSubView: ctxtValView toRightOf: ctxtVarView.
  29974.     topView label: aString.
  29975.     topView minimumSize: aPoint.
  29976.     ^ topView
  29977. ! !
  29978.  
  29979. !Debugger methodsFor: 'initialize' stamp: 'jm 5/1/1998 17:47'!
  29980. buildMVCNotifierViewLabel: aString message: messageString minSize: aPoint
  29981.  
  29982.     | topView aStringHolderView |
  29983.     topView _ StandardSystemView new model: self.
  29984.     topView borderWidth: 1.
  29985.     aStringHolderView _ PluggableTextView on: self
  29986.         text: #contents
  29987.         accept: #doNothing:
  29988.         readSelection: #contentsSelection
  29989.         menu: #debugProceedMenu:.
  29990.     aStringHolderView
  29991.         editString: messageString;
  29992.         askBeforeDiscardingEdits: false.
  29993.     topView
  29994.         addSubView: aStringHolderView;
  29995.         label: aString;
  29996.         minimumSize: aPoint.
  29997.     ^ topView
  29998. ! !
  29999.  
  30000. !Debugger methodsFor: 'initialize' stamp: 'di 5/6/1998 21:37'!
  30001. buildMorphicNotifierLabelled: label message: messageString
  30002.     | notifyPane window |
  30003.     window _ (SystemWindow labelled: label) model: self.
  30004.  
  30005.     notifyPane _ PluggableTextMorph on: self text: #contents accept: #doNothing:
  30006.         readSelection: #contentsSelection menu: #debugProceedMenu:.
  30007.     notifyPane editString: messageString;
  30008.         askBeforeDiscardingEdits: false.
  30009.     window addMorph: notifyPane frame: (0@0 corner: 1@1).
  30010.  
  30011.     ^ window openInWorldExtent: 350@116! !
  30012.  
  30013. !Debugger methodsFor: 'initialize'!
  30014. defaultBackgroundColor
  30015.     ^ #lightRed! !
  30016.  
  30017. !Debugger methodsFor: 'initialize' stamp: 'tm 5/10/1998 15:08'!
  30018. openFullMorphicLabel: labelString
  30019.     | window |
  30020.     self expandStack.
  30021.     window _ (SystemWindow labelled: labelString) model: self.
  30022.  
  30023.     window addMorph: (PluggableListMorph on: self list: #contextStackList
  30024.             selected: #contextStackIndex changeSelected: #toggleContextStackIndex:
  30025.             menu: #contextStackMenu:shifted: keystroke: #contextStackKey:from:)
  30026.         frame: (0@0 corner: 1@0.3).
  30027.     window addMorph: (PluggableTextMorph on: self
  30028.             text: #contents accept: #contents:notifying:
  30029.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:)
  30030.         frame: (0@0.3 corner: 1@0.7).
  30031.     window addMorph: (PluggableListMorph on: self receiverInspector list: #fieldList
  30032.             selected: #selectionIndex changeSelected: #toggleIndex:
  30033.             menu: #fieldListMenu: keystroke: #inspectorKey:from:)
  30034.         frame: (0@0.7 corner: 0.2@1).
  30035.     window addMorph: (PluggableTextMorph on: self receiverInspector
  30036.             text: #contents accept: #accept:
  30037.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:)
  30038.         frame: (0.2@0.7 corner: 0.5@1).
  30039.     window addMorph: (PluggableListMorph on: self contextVariablesInspector list: #fieldList
  30040.             selected: #selectionIndex changeSelected: #toggleIndex:
  30041.             menu: #fieldListMenu: keystroke: #inspectorKey:from:)
  30042.         frame: (0.5@0.7 corner: 0.7@1).
  30043.     window addMorph: (PluggableTextMorph on: self contextVariablesInspector
  30044.             text: #contents accept: #accept:
  30045.             readSelection: #contentsSelection menu: #codePaneMenu:shifted:)
  30046.         frame: (0.7@0.7 corner: 1@1).
  30047.  
  30048.     ^ window openInWorld
  30049. ! !
  30050.  
  30051. !Debugger methodsFor: 'initialize' stamp: 'jm 5/1/1998 18:03'!
  30052. openFullNoSuspendLabel: aString
  30053.     "Create and schedule a full debugger with the given label. Do not terminate the current active process."
  30054.  
  30055.     | topView |
  30056.     topView _ self buildMVCDebuggerViewLabel: aString minSize: 300@200.
  30057.     topView controller openNoTerminate.
  30058.     ^ topView
  30059. ! !
  30060.  
  30061. !Debugger methodsFor: 'initialize' stamp: 'di 5/4/1998 23:01'!
  30062. openNotifierContents: msgString label: label
  30063.     "Create and schedule a notifier view with the given label and message. A notifier view shows just the message or the first several lines of the stack, with a menu that allows the user to open a full debugger if so desired. Do not terminate the current active process."
  30064.     | msg topView p newActiveProcess |
  30065.     Sensor flushKeyboard.
  30066.     (label beginsWith: 'Space is low')
  30067.         ifTrue: [msg _ self lowSpaceChoices, msgString]
  30068.         ifFalse: [msg _ msgString].
  30069.  
  30070.     World ifNotNil:
  30071.         [self buildMorphicNotifierLabelled: label message: msg.
  30072.         newActiveProcess _
  30073.             [[true] whileTrue: [World doOneCycle.  Processor yield]] newProcess
  30074.                     priority: Processor userSchedulingPriority.
  30075.         ^ newActiveProcess resume].
  30076.  
  30077.     Display fullScreen.
  30078.     Cursor normal show.
  30079.     topView _ self buildMVCNotifierViewLabel: label message: msg minSize: 350@((14 * 5) + 16).
  30080.     ScheduledControllers activeController
  30081.         ifNil: [p _ Display boundingBox center]
  30082.         ifNotNil: [p _ ScheduledControllers activeController view displayBox center].
  30083.     topView controller openNoTerminateDisplayAt: (p max: (200@60)).
  30084.     ^ topView
  30085. ! !
  30086.  
  30087. !Debugger methodsFor: 'initialize'!
  30088. release
  30089.  
  30090.     interruptedProcess ~~ nil ifTrue: [interruptedProcess terminate].
  30091.     interruptedProcess _ nil.
  30092.     interruptedController _ nil.
  30093.     contextStack _ nil.
  30094.     contextStackTop _ nil.
  30095.     receiverInspector _ nil.
  30096.     contextVariablesInspector _ nil.
  30097.     Smalltalk installLowSpaceWatcher.  "restart low space handler"
  30098.     super release.! !
  30099.  
  30100.  
  30101. !Debugger methodsFor: 'accessing'!
  30102. contents 
  30103.     "Depending on the current selection, different information is retrieved.
  30104.     Answer a string description of that information.  This information is the
  30105.     method in the currently selected context."
  30106.  
  30107.     contents == nil ifTrue: [^''].
  30108.     ^contents! !
  30109.  
  30110. !Debugger methodsFor: 'accessing' stamp: 'tk 12/6/97 21:31'!
  30111. contents: aText notifying: aController 
  30112.     "The retrieved information has changed and its source must now be 
  30113.     updated. In this case, the retrieved information is the method of the 
  30114.     selected context."
  30115.     | selector classOfMethod category method priorMethod parseNode |
  30116.     contextStackIndex = 0 ifTrue: [^self].
  30117.     (self selectedContext isKindOf: MethodContext)
  30118.         ifFalse:
  30119.             [(self confirm:
  30120. 'I will have to revert to the method from
  30121. which this block originated.  Is that OK?')
  30122.                 ifTrue: [self resetContext: self selectedContext home]
  30123.                 ifFalse: [^self]].
  30124.     classOfMethod _ self selectedClass.
  30125.     category _ self selectedMessageCategoryName.
  30126.     Cursor execute showWhile:
  30127.         [method _ classOfMethod
  30128.         compile: aText
  30129.         notifying: aController
  30130.         trailer: #(0 0 0 0)
  30131.         ifFail: [^ false]
  30132.         elseSetSelectorAndNode: 
  30133.             [:sel :methodNode | selector _ sel.
  30134.             selector == self selectedMessageName
  30135.                 ifFalse: [self notify: 'can''t change selector'. ^ false].
  30136.             priorMethod _ (classOfMethod includesSelector: selector)
  30137.                 ifTrue: [classOfMethod compiledMethodAt: selector]
  30138.                 ifFalse: [nil].
  30139.             sourceMap _ methodNode sourceMap.
  30140.             tempNames _ methodNode tempNames.
  30141.             parseNode _ methodNode].
  30142.         method cacheTempNames: tempNames].
  30143.     category isNil ifFalse: "Skip this for DoIts"
  30144.         [method putSource: aText
  30145.                 fromParseNode: parseNode
  30146.                 class: classOfMethod
  30147.                 category: category
  30148.                 inFile: 2 priorMethod: priorMethod.
  30149.         classOfMethod organization classify: selector under: category].
  30150.     contents _ aText copy.
  30151.     self selectedContext restartWith: method.
  30152.     contextVariablesInspector object: nil.
  30153.     self resetContext: self selectedContext.
  30154.     ^true! !
  30155.  
  30156. !Debugger methodsFor: 'accessing'!
  30157. contextVariablesInspector
  30158.     "Answer the instance of Inspector that is providing a view of the 
  30159.     variables of the selected context."
  30160.  
  30161.     ^contextVariablesInspector! !
  30162.  
  30163. !Debugger methodsFor: 'accessing' stamp: 'tk 4/16/1998 12:16'!
  30164. doNothing: newText
  30165.     "Notifier window can't accept text"! !
  30166.  
  30167. !Debugger methodsFor: 'accessing'!
  30168. interruptedContext
  30169.     "Answer the suspended context of the interrupted process."
  30170.  
  30171.     ^contextStackTop! !
  30172.  
  30173. !Debugger methodsFor: 'accessing'!
  30174. interruptedProcess
  30175.     "Answer the interrupted process."
  30176.  
  30177.     ^interruptedProcess! !
  30178.  
  30179. !Debugger methodsFor: 'accessing' stamp: 'tk 4/16/1998 15:47'!
  30180. isNotifier
  30181.     "Return true if this debugger has not been expanded into a full sized window"
  30182.  
  30183.     ^ receiverInspector == nil! !
  30184.  
  30185. !Debugger methodsFor: 'accessing'!
  30186. proceedValue
  30187.     "Answer the value to return to the selected context when the interrupted 
  30188.     process proceeds."
  30189.  
  30190.     ^proceedValue! !
  30191.  
  30192. !Debugger methodsFor: 'accessing'!
  30193. proceedValue: anObject 
  30194.     "Set the value to be returned to the selected context when the interrupted 
  30195.     process proceeds."
  30196.  
  30197.     proceedValue _ anObject! !
  30198.  
  30199. !Debugger methodsFor: 'accessing'!
  30200. receiver
  30201.     "Answer the receiver of the selected context, if any. Answer nil 
  30202.     otherwise."
  30203.  
  30204.     contextStackIndex = 0
  30205.         ifTrue: [^nil]
  30206.         ifFalse: [^self selectedContext receiver]! !
  30207.  
  30208. !Debugger methodsFor: 'accessing'!
  30209. receiverInspector
  30210.     "Answer the instance of Inspector that is providing a view of the 
  30211.     variables of the selected context's receiver."
  30212.  
  30213.     ^receiverInspector! !
  30214.  
  30215.  
  30216. !Debugger methodsFor: 'notifier menu' stamp: 'di 5/5/1998 00:00'!
  30217. debug
  30218.     "Open a full DebuggerView."
  30219.     | topView |
  30220.     topView _ self topView.
  30221.     topView model: nil.  "so close won't release me."
  30222.     World ifNotNil:
  30223.         [self openFullMorphicLabel: topView label.
  30224.         ^ topView delete].
  30225.     topView controller controlTerminate.
  30226.     topView deEmphasizeView; erase.
  30227.     self openFullNoSuspendLabel: topView label.
  30228.     topView controller closeAndUnscheduleNoErase.
  30229.     Processor terminateActive.
  30230. ! !
  30231.  
  30232.  
  30233. !Debugger methodsFor: 'context stack (message list)'!
  30234. contextStackIndex
  30235.     "Answer the index of the selected context."
  30236.  
  30237.     ^contextStackIndex! !
  30238.  
  30239. !Debugger methodsFor: 'context stack (message list)'!
  30240. contextStackList
  30241.     "Answer the array of contexts."
  30242.  
  30243.     ^contextStackList! !
  30244.  
  30245. !Debugger methodsFor: 'context stack (message list)' stamp: 'tk 4/17/1998 18:05'!
  30246. expandStack
  30247.     "A Notifier is being turned into a full debugger.  Show a substantial amount of stack in the context pane."
  30248.  
  30249.     self newStack: (contextStackTop stackOfSize: 20).
  30250.     contextStackIndex _ 0.
  30251.     receiverInspector _ Inspector inspect: nil.
  30252.     contextVariablesInspector _ ContextVariablesInspector inspect: nil.
  30253.     proceedValue _ nil! !
  30254.  
  30255. !Debugger methodsFor: 'context stack (message list)'!
  30256. fullyExpandStack
  30257.     "Expand the stack to include all of it, rather than the first four or five
  30258.     contexts."
  30259.  
  30260.     self okToChange ifFalse: [^ self].
  30261.     self newStack: contextStackTop stack.
  30262.     self changed: #contextStackList! !
  30263.  
  30264. !Debugger methodsFor: 'context stack (message list)'!
  30265. messageListIndex
  30266.     "Answer the index of the currently selected context."
  30267.  
  30268.     ^contextStackIndex! !
  30269.  
  30270. !Debugger methodsFor: 'context stack (message list)'!
  30271. selectedMessage
  30272.     "Answer the source code of the currently selected context."
  30273.  
  30274.     contents == nil ifTrue: [contents _ self selectedContext sourceCode].
  30275.     ^contents! !
  30276.  
  30277. !Debugger methodsFor: 'context stack (message list)'!
  30278. selectedMessageName
  30279.     "Answer the message selector of the currently selected context."
  30280.  
  30281.     ^self selectedContext selector! !
  30282.  
  30283. !Debugger methodsFor: 'context stack (message list)' stamp: 'tk 4/6/98 23:00'!
  30284. spawn: aString 
  30285.     "Create and schedule a message browser on the message, aString. Any 
  30286.     edits already made are retained."
  30287.  
  30288.     self messageListIndex > 0
  30289.         ifTrue: 
  30290.             [^Browser
  30291.                 openMessageBrowserForClass: self selectedClass
  30292.                 selector: self selectedMessageName
  30293.                 editString: aString]! !
  30294.  
  30295. !Debugger methodsFor: 'context stack (message list)'!
  30296. toggleContextStackIndex: anInteger 
  30297.     "If anInteger is the same as the index of the selected context, deselect it. 
  30298.     Otherwise, the context whose index is anInteger becomes the selected 
  30299.     context."
  30300.  
  30301.     self contextStackIndex: 
  30302.         (contextStackIndex = anInteger
  30303.             ifTrue: [0]
  30304.             ifFalse: [anInteger])
  30305.         oldContextWas:
  30306.         (contextStackIndex = 0
  30307.             ifTrue: [nil]
  30308.             ifFalse: [contextStack at: contextStackIndex])! !
  30309.  
  30310.  
  30311. !Debugger methodsFor: 'context stack menu' stamp: 'wod 5/15/1998 00:24'!
  30312. browseMessages
  30313.     "Present a menu of all messages sent by the currently selected message.
  30314.     Open a message set browser of all implementors of the message chosen.
  30315.     Do nothing if no message is chosen."
  30316.  
  30317.     contextStackIndex = 0 ifTrue: [^ self].
  30318.     super browseMessages.! !
  30319.  
  30320. !Debugger methodsFor: 'context stack menu' stamp: 'wod 5/15/1998 00:23'!
  30321. browseSendersOfMessages
  30322.     "Present a menu of the currently selected message, as well as all
  30323.     messages sent by it.  Open a message set browser of all implementors
  30324.     of the message chosen."
  30325.  
  30326.     contextStackIndex = 0 ifTrue: [^ self].
  30327.     super browseSendersOfMessages! !
  30328.  
  30329. !Debugger methodsFor: 'context stack menu' stamp: 'sw 8/6/97 14:26'!
  30330. browseVersions
  30331.     "Create and schedule a message set browser on all versions of the 
  30332.     currently selected message selector."
  30333.     | class selector |
  30334.     class _ self selectedClassOrMetaClass.
  30335.     selector _ self selectedMessageName.
  30336.     ChangeList
  30337.         browseVersionsOf: (class compiledMethodAt: selector)
  30338.         class: self selectedClass
  30339.         meta: self selectedClass isMeta
  30340.         category: self selectedMessageCategoryName
  30341.         selector: selector! !
  30342.  
  30343. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/6/98 23:00'!
  30344. buildMessageBrowser
  30345.     "Create and schedule a message browser on the current method."
  30346.  
  30347.     contextStackIndex = 0 ifTrue: [^ self].
  30348.     ^ Browser
  30349.         openMessageBrowserForClass: self selectedClassOrMetaClass
  30350.         selector: self selectedMessageName
  30351.         editString: nil! !
  30352.  
  30353. !Debugger methodsFor: 'context stack menu'!
  30354. close: aScheduledController 
  30355.     "The argument is a controller on a view of the receiver.
  30356.     That view is closed."
  30357.  
  30358.     aScheduledController close
  30359. ! !
  30360.  
  30361. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/18/1998 09:24'!
  30362. contextStackKey: aChar from: view
  30363.     "Respond to a keystroke in the context list"
  30364.  
  30365.      | selector |
  30366.     selector _ ContextStackKeystrokes at: aChar ifAbsent: [nil].
  30367.     selector ifNil: [self messageListKey: aChar from: view]
  30368.         ifNotNil: [self perform: selector]! !
  30369.  
  30370. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/21/1998 07:51'!
  30371. contextStackMenu: aMenu shifted: shifted
  30372.     ^ shifted ifFalse: [aMenu labels: 
  30373. 'fullStack (f)
  30374. restart (r)
  30375. proceed (p)
  30376. step (t)
  30377. send (e)
  30378. where (w)
  30379. senders of...
  30380. implementors of...
  30381. method inheritance
  30382. versions
  30383. inst var refs...
  30384. inst var defs...
  30385. class var refs...
  30386. class variables
  30387. class refs
  30388. browse full
  30389. more...'
  30390.     lines: #(6 10 12 15)
  30391.     selections: #(fullStack restart proceed step send where
  30392. browseSendersOfMessages browseMessages methodHierarchy browseVersions
  30393. browseInstVarRefs browseInstVarDefs
  30394. browseClassVarRefs browseClassVariables browseClassRefs
  30395. browseMethodFull
  30396. shiftedYellowButtonActivity)]
  30397.  
  30398.     ifTrue: [aMenu labels: 
  30399. 'browse class hierarchy
  30400. browse class
  30401. browse method
  30402. implementors of sent messages
  30403. change sets with this method
  30404. inspect instances
  30405. inspect subinstances
  30406. remove from current change set
  30407. more...' 
  30408.     lines: #(5 7 9)
  30409.     selections: #(classHierarchy browseClass 
  30410.         buildMessageBrowser browseAllMessages findMethodInChangeSets 
  30411.         inspectInstances inspectSubInstances
  30412.         removeFromCurrentChanges
  30413.         unshiftedYellowButtonActivity)]
  30414.  
  30415. ! !
  30416.  
  30417. !Debugger methodsFor: 'context stack menu' stamp: 'sw 8/6/97 13:45'!
  30418. currentCompiledMethod
  30419.     ^ self selectedClassOrMetaClass compiledMethodAt: self selectedMessageName! !
  30420.  
  30421. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/16/1998 12:19'!
  30422. debugProceedMenu: aMenu
  30423.     ^ aMenu labels: 
  30424. 'proceed
  30425. debug'
  30426.     lines: #()
  30427.     selections: #(proceed debug )
  30428. ! !
  30429.  
  30430. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/15/1998 16:55'!
  30431. down
  30432.     "move down the context stack to the previous (enclosing) context"
  30433.  
  30434.     self toggleContextStackIndex: contextStackIndex+1! !
  30435.  
  30436. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/17/1998 18:06'!
  30437. fullStack
  30438.     "Change from displaying the minimal stack to a full one."
  30439.  
  30440.     self contextStackList size > 20 "Already expanded"
  30441.         ifTrue:
  30442.             [self changed: #flash]
  30443.         ifFalse:
  30444.             [self contextStackIndex = 0 ifFalse: [
  30445.                 self toggleContextStackIndex: self contextStackIndex].
  30446.             self fullyExpandStack]! !
  30447.  
  30448. !Debugger methodsFor: 'context stack menu' stamp: 'di 5/5/1998 00:07'!
  30449. proceed
  30450.     "Proceed execution of the receiver's model, starting after the expression at 
  30451.     which an interruption occurred."
  30452.  
  30453.     Smalltalk okayToProceedEvenIfSpaceIsLow ifTrue: [
  30454.         self proceed: self topView].
  30455. ! !
  30456.  
  30457. !Debugger methodsFor: 'context stack menu' stamp: 'di 5/5/1998 00:07'!
  30458. proceed: aTopView 
  30459.     "Proceed from the interrupted state of the currently selected context. The 
  30460.     argument is the topView of the receiver. That view is closed."
  30461.  
  30462.     self okToChange ifFalse: [^ self].
  30463.     self checkContextSelection.
  30464.     contextStackIndex > 1 | externalInterrupt not 
  30465.         ifTrue: [self selectedContext push: proceedValue].
  30466.     self resumeProcess: aTopView! !
  30467.  
  30468. !Debugger methodsFor: 'context stack menu' stamp: 'di 5/5/1998 00:08'!
  30469. restart
  30470.     "Proceed execution of the receiver's model, starting at the beginning of 
  30471.     the currently selected method."
  30472.  
  30473.     self restart: self topView.
  30474. ! !
  30475.  
  30476. !Debugger methodsFor: 'context stack menu' stamp: 'di 5/5/1998 00:08'!
  30477. restart: aTopView 
  30478.     "Proceed from the initial state of the currently selected context. The 
  30479.     argument is a controller on a view of the receiver. That view is closed."
  30480.  
  30481.     self okToChange ifFalse: [^ self].
  30482.     self checkContextSelection.
  30483.     (self selectedContext isKindOf: MethodContext)
  30484.         ifFalse:
  30485.             [(self confirm:
  30486. 'I will have to revert to the method from
  30487. which this block originated.  Is that OK?')
  30488.                 ifTrue: [self resetContext: self selectedContext home]
  30489.                 ifFalse: [^self]].
  30490.     self selectedContext restart.
  30491.     self resumeProcess: aTopView! !
  30492.  
  30493. !Debugger methodsFor: 'context stack menu'!
  30494. selectPC
  30495.     "Toggle the flag telling whether to automatically select the expression 
  30496.     currently being executed by the selected context."
  30497.  
  30498.     selectingPC _ selectingPC not! !
  30499.  
  30500. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/16/1998 11:36'!
  30501. send
  30502.     "Send the selected message in the accessed method, and take control in 
  30503.     the method invoked to allow further step or 
  30504. send."
  30505.  
  30506.     | currentContext |
  30507.     "Sensor leftShiftDown ifTrue: [self halt]."
  30508.     self okToChange ifFalse: [^ self].
  30509.     self checkContextSelection.
  30510.     externalInterrupt ifFalse: [contextStackTop push: proceedValue].
  30511.     externalInterrupt _ true. "simulation leaves same state as interrupting"
  30512.     currentContext _ self selectedContext.
  30513.     currentContext stepToSendOrReturn.
  30514.     self contextStackIndex > 1 | currentContext willReturn
  30515.         ifTrue: 
  30516.             [self changed: #notChanged]
  30517.         ifFalse: 
  30518.             [currentContext _ currentContext step.
  30519.             currentContext stepToSendOrReturn.
  30520.             self resetContext: currentContext]! !
  30521.  
  30522. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/18/1998 15:08'!
  30523. shiftedYellowButtonActivity
  30524.     "Invoke the model's other menu.  Just do what the controller would have done."
  30525.  
  30526.     | menu |
  30527.     menu _ self contextStackMenu: (CustomMenu new) shifted: true.
  30528.     menu == nil
  30529.         ifTrue: [Sensor waitNoButton]
  30530.         ifFalse: [menu invokeOn: self].
  30531. ! !
  30532.  
  30533. !Debugger methodsFor: 'context stack menu' stamp: 'sn 9/6/97 16:27'!
  30534. step
  30535.     "Send the selected message in the accessed method, and regain control 
  30536.     after the invoked method returns."
  30537.     
  30538.     | currentContext oldMethod |
  30539.     self okToChange ifFalse: [^ self].
  30540.     self checkContextSelection.
  30541.     externalInterrupt ifFalse: [contextStackTop push: proceedValue].
  30542.     externalInterrupt _ true. "simulation leaves same state as interrupting"
  30543.     currentContext _ self selectedContext.
  30544.     self contextStackIndex > 1
  30545.         ifTrue: 
  30546.             [currentContext completeCallee: contextStackTop.
  30547.             self resetContext: currentContext]
  30548.         ifFalse: 
  30549.             [currentContext stepToSendOrReturn.
  30550.             currentContext willReturn
  30551.                 ifTrue: 
  30552.                     [oldMethod _ currentContext method.
  30553.                     currentContext _ currentContext step.
  30554.                     currentContext stepToSendOrReturn.
  30555.                     self resetContext: currentContext.
  30556.                     oldMethod == currentContext method "didnt used to update pc here"
  30557.                         ifTrue: [self changed: #pc]]
  30558.                 ifFalse: 
  30559.                     [currentContext completeCallee: currentContext step.
  30560.                     self changed: #pc.
  30561.                     self updateInspectors]]! !
  30562.  
  30563. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/21/1998 09:05'!
  30564. unshiftedYellowButtonActivity
  30565.     "Invoke the model's other menu.  Just do what the controller would have done."
  30566.  
  30567.     | menu |
  30568.     menu _ self contextStackMenu: (CustomMenu new) shifted: false.
  30569.     menu == nil
  30570.         ifTrue: [Sensor waitNoButton]
  30571.         ifFalse: [menu invokeOn: self].
  30572. ! !
  30573.  
  30574. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/15/1998 16:55'!
  30575. up
  30576.     "move up the context stack to the next (enclosed) context"
  30577.  
  30578.     contextStackIndex > 1 ifTrue: [self toggleContextStackIndex: contextStackIndex-1]! !
  30579.  
  30580. !Debugger methodsFor: 'context stack menu' stamp: 'tk 4/15/1998 16:54'!
  30581. where
  30582.     "Select the expression whose evaluation was interrupted."
  30583.  
  30584.     self selectPC! !
  30585.  
  30586.  
  30587. !Debugger methodsFor: 'code pane' stamp: 'tk 4/15/1998 18:31'!
  30588. contentsSelection
  30589.  
  30590.     ^ self pcRange! !
  30591.  
  30592. !Debugger methodsFor: 'code pane'!
  30593. doItContext
  30594.     "Answer the context in which a text selection can be evaluated."
  30595.  
  30596.     contextStackIndex = 0
  30597.         ifTrue: [^super doItContext]
  30598.         ifFalse: [^self selectedContext]! !
  30599.  
  30600. !Debugger methodsFor: 'code pane'!
  30601. doItReceiver
  30602.     "Answer the object that should be informed of the result of evaluating a
  30603.     text selection."
  30604.  
  30605.     ^self receiver! !
  30606.  
  30607. !Debugger methodsFor: 'code pane' stamp: 'tk 5/2/1998 10:04'!
  30608. pc
  30609.  
  30610.     ^ self pcRange! !
  30611.  
  30612. !Debugger methodsFor: 'code pane'!
  30613. pcRange
  30614.     "Answer the indices in the source code for the method corresponding to 
  30615.     the selected context's program counter value."
  30616.  
  30617.     | i methodNode pc end |
  30618.     (selectingPC and: [contextStackIndex ~= 0])
  30619.         ifFalse: [^1 to: 0].
  30620.     sourceMap == nil ifTrue:
  30621.         [methodNode _ self selectedClass compilerClass new
  30622.             parse: self selectedMessage
  30623.             in: self selectedClass
  30624.             notifying: nil.
  30625.         sourceMap _ methodNode sourceMap.
  30626.         tempNames _ methodNode tempNames.
  30627.         self selectedContext method cacheTempNames: tempNames].
  30628.     sourceMap size = 0 ifTrue: [^1 to: 0].
  30629.     pc_ self selectedContext pc -
  30630.         ((externalInterrupt and: [contextStackIndex=1])
  30631.             ifTrue: [1]
  30632.             ifFalse: [2]).
  30633.     i _ sourceMap indexForInserting: (Association key: pc value: nil).
  30634.     i < 1 ifTrue: [^1 to: 0].
  30635.     i > sourceMap size
  30636.         ifTrue:
  30637.             [end _ sourceMap inject: 0 into:
  30638.                 [:prev :this | prev max: this value last].
  30639.             ^ end+1 to: end].
  30640.     ^(sourceMap at: i) value! !
  30641.  
  30642.  
  30643. !Debugger methodsFor: 'code pane menu' stamp: 'tk 4/17/1998 17:25'!
  30644. perform: selector orSendTo: otherTarget
  30645.     "Selector was just chosen from a menu by a user.  If can respond, then perform it on myself.  If not, send it to otherTarget, presumably the editPane from which the menu was invoked." 
  30646.  
  30647.     | result |
  30648.     (#(debug proceed) includes: selector)        "When I am a notifier window"
  30649.         ifTrue: [^ self perform: selector]
  30650.         ifFalse: [result _ super perform: selector orSendTo: otherTarget.
  30651.                 selector == #doIt ifTrue: [
  30652.                     result ~~ #failedDoit ifTrue: [self proceedValue: result]].
  30653.                 ^ result]! !
  30654.  
  30655.  
  30656. !Debugger methodsFor: 'message category list'!
  30657. selectedMessageCategoryName
  30658.     "Answer the name of the message category of the message of the 
  30659.     currently selected context."
  30660.  
  30661.     ^self selectedClass organization categoryOfElement: self selectedMessageName! !
  30662.  
  30663.  
  30664. !Debugger methodsFor: 'class list'!
  30665. selectedClass
  30666.     "Answer the class in which the currently selected context's method was 
  30667.     found."
  30668.  
  30669.     ^self selectedContext mclass! !
  30670.  
  30671. !Debugger methodsFor: 'class list'!
  30672. selectedClassOrMetaClass
  30673.     "Answer the class in which the currently selected context's method was 
  30674.     found."
  30675.  
  30676.     ^self selectedContext mclass! !
  30677.  
  30678.  
  30679. !Debugger methodsFor: 'dependents access'!
  30680. updateInspectors 
  30681.     "Update the inspectors on the receiver's variables."
  30682.  
  30683.     receiverInspector update.
  30684.     contextVariablesInspector update! !
  30685.  
  30686.  
  30687. !Debugger methodsFor: 'private'!
  30688. checkContextSelection
  30689.  
  30690.     contextStackIndex = 0 ifTrue: [contextStackIndex _ 1]! !
  30691.  
  30692. !Debugger methodsFor: 'private' stamp: 'di 5/13/1998 14:07'!
  30693. contextStackIndex: anInteger oldContextWas: oldContext
  30694.  
  30695.     | newMethod |
  30696.     contextStackIndex _ anInteger.
  30697.     anInteger = 0
  30698.         ifTrue:
  30699.             [tempNames _ sourceMap _ contents _ nil.
  30700.             self changed: #contextStackIndex.
  30701.             self changed: #contents.
  30702.             contextVariablesInspector object: nil.
  30703.             receiverInspector object: self receiver.
  30704.             ^self].
  30705.     (newMethod _ oldContext == nil or:
  30706.         [oldContext method ~~ self selectedContext method])
  30707.         ifTrue:
  30708.             [tempNames _ sourceMap _ nil.
  30709.             contents _ self selectedContext sourceCode.
  30710.             self changed: #contents.
  30711.             self pcRange "will compute tempNamesunless noFrills"].
  30712.     self changed: #contextStackIndex.
  30713.     tempNames == nil
  30714.         ifTrue: [tempNames _ 
  30715.                     self selectedClassOrMetaClass parserClass new parseArgsAndTemps: contents notifying: nil].
  30716.     contextVariablesInspector object: self selectedContext.
  30717.     receiverInspector object: self receiver.
  30718.     newMethod ifFalse: [self changed: #contentsSelection]! !
  30719.  
  30720. !Debugger methodsFor: 'private'!
  30721. externalInterrupt: aBoolean
  30722.  
  30723.     externalInterrupt _ aBoolean ! !
  30724.  
  30725. !Debugger methodsFor: 'private' stamp: 'jm 5/1/1998 16:20'!
  30726. lowSpaceChoices
  30727.     "Return a notifier message string to be presented when space is running low."
  30728.  
  30729.     ^ 'Warning!! Squeak is almost out of memory!!
  30730.  
  30731. Low space detection is now disabled. It will be restored when you close or proceed from this error notifier. Don''t panic, but do proceed with caution.
  30732.  
  30733. Here are some suggestions:
  30734.  
  30735. ƒ If you suspect an infinite recursion (the same methods calling each other again and again), then close this debugger, and fix the problem.
  30736.  
  30737. ƒ If you want this computation to finish, then make more space available (read on) and choose "proceed" in this debugger. Here are some ways to make more space available...
  30738.    > Close any windows that are not needed.
  30739.    > Get rid of some large objects (e.g., images).
  30740.    > Leave this window on the screen, choose "save as..." from the screen menu, quit, restart the Squeak VM with a larger memory allocation, then restart the image you just saved, and choose "proceed" in this window.
  30741.  
  30742. ƒ If you want to investigate further, choose "debug" in this window.  Do not use the debugger "fullStack" command unless you are certain that the stack is not very deep. (Trying to show the full stack will definitely use up all remaining memory if the low-space problem is caused by an infinite recursion!!).
  30743.  
  30744. '
  30745. ! !
  30746.  
  30747. !Debugger methodsFor: 'private'!
  30748. newStack: stack
  30749.     | oldStack diff |
  30750.     oldStack _ contextStack.
  30751.     contextStack _ stack.
  30752.     (oldStack == nil or: [oldStack last ~~ stack last])
  30753.         ifTrue: [contextStackList _ contextStack collect: [:ctx | ctx printString].
  30754.                 ^ self].
  30755.     "May be able to re-use some of previous list"
  30756.     diff _ stack size - oldStack size.
  30757.     contextStackList _ diff <= 0
  30758.         ifTrue: [contextStackList copyFrom: 1-diff to: oldStack size]
  30759.         ifFalse: [diff > 1
  30760.                 ifTrue: [contextStack collect: [:ctx | ctx printString]]
  30761.                 ifFalse: [(Array with: stack first printString) , contextStackList]]! !
  30762.  
  30763. !Debugger methodsFor: 'private'!
  30764. process: aProcess controller: aController context: aContext
  30765.  
  30766.     super initialize.
  30767.     contents _ nil. 
  30768.     interruptedProcess _ aProcess.
  30769.     interruptedController _ aController.
  30770.     contextStackTop _ aContext.
  30771.     self newStack: (contextStackTop stackOfSize: 1).
  30772.     contextStackIndex _ 1.
  30773.     externalInterrupt _ false.
  30774.     selectingPC _ true! !
  30775.  
  30776. !Debugger methodsFor: 'private' stamp: 'tk 4/15/1998 19:04'!
  30777. resetContext: aContext 
  30778.     "Used when a new context becomes top-of-stack, for instance when the
  30779.     method of the selected context is re-compiled, or the simulator steps or
  30780.     returns to a new method. There is room for much optimization here, first
  30781.     to save recomputing the whole stack list (and text), and secondly to avoid
  30782.     recomposing all that text (by editing the paragraph instead of recreating it)."
  30783.  
  30784.     | oldContext |
  30785.     oldContext _ self selectedContext.
  30786.     contextStackTop _ aContext.
  30787.     self newStack: contextStackTop stack.
  30788.     self changed: #contextStackList.
  30789.     self contextStackIndex: 1 oldContextWas: oldContext.
  30790.     self changed: #content.! !
  30791.  
  30792. !Debugger methodsFor: 'private' stamp: 'di 5/5/1998 00:20'!
  30793. resumeProcess: aTopView
  30794.     World ifNil: [aTopView erase].
  30795.     Smalltalk installLowSpaceWatcher.  "restart low space handler"
  30796.     interruptedProcess suspendedContext method
  30797.             == (Process compiledMethodAt: #terminate) ifFalse:
  30798.         [contextStackIndex > 1
  30799.             ifTrue: [interruptedProcess popTo: self selectedContext]
  30800.             ifFalse: [interruptedProcess install: self selectedContext].
  30801.         World ifNil: [ScheduledControllers
  30802.                         activeControllerNoTerminate: interruptedController
  30803.                         andProcess: interruptedProcess]
  30804.             ifNotNil: [interruptedProcess resume]].
  30805.     "if old process was terminated, just terminate current one"
  30806.     interruptedProcess _ nil. 
  30807.     World ifNil: [aTopView controller closeAndUnscheduleNoErase]
  30808.         ifNotNil: [aTopView delete].
  30809.     Processor terminateActive
  30810. ! !
  30811.  
  30812. !Debugger methodsFor: 'private'!
  30813. selectedContext
  30814.  
  30815.     contextStackIndex = 0
  30816.         ifTrue: [^contextStackTop]
  30817.         ifFalse: [^contextStack at: contextStackIndex]! !
  30818.  
  30819. "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
  30820.  
  30821. Debugger class
  30822.     instanceVariableNames: ''!
  30823.  
  30824. !Debugger class methodsFor: 'class initialization' stamp: 'di 5/22/1998 14:52'!
  30825. initialize
  30826.     ErrorRecursion _ false.
  30827.     ContextStackKeystrokes _ Dictionary new
  30828.         at: $e put: #send;
  30829.         at: $t put: #step;
  30830.         at: $p put: #proceed;
  30831.         at: $r put: #restart;
  30832.         at: $f put: #fullStack;
  30833.         at: $w put: #where;
  30834.         yourself.
  30835.  
  30836.     "Debugger initialize"! !
  30837.  
  30838.  
  30839. !Debugger class methodsFor: 'instance creation' stamp: 'jm 5/1/1998 16:31'!
  30840. context: aContext 
  30841.     "Answer an instance of me for debugging the active process starting with the given context."
  30842.  
  30843.     ^ self new
  30844.         process: Processor activeProcess
  30845.         controller:
  30846.             (ScheduledControllers inActiveControllerProcess
  30847.                 ifTrue: [ScheduledControllers activeController]
  30848.                 ifFalse: [nil])
  30849.         context: aContext
  30850. ! !
  30851.  
  30852.  
  30853. !Debugger class methodsFor: 'opening' stamp: 'di 5/4/1998 15:43'!
  30854. openContext: aContext label: aString contents: contentsString
  30855.     "Open a notifier in response to an error, halt, or notify. A notifier view just shows a short view of the sender stack and provides a menu that lets the user open a full debugger."
  30856.  
  30857.     ErrorRecursion ifTrue:
  30858.         [ErrorRecursion _ false.
  30859.         self primitiveError: aString].
  30860.     ErrorRecursion _ true.
  30861.     (Debugger context: aContext)
  30862.         openNotifierContents: contentsString
  30863.         label: aString.
  30864.     ErrorRecursion _ false.
  30865.     Processor activeProcess suspend.
  30866. ! !
  30867.  
  30868. !Debugger class methodsFor: 'opening' stamp: 'jm 5/1/1998 18:05'!
  30869. openInterrupt: aString onProcess: interruptedProcess
  30870.     "Open a notifier in response to an interrupt. An interrupt occurs when the user types the interrupt key (cmd-. on Macs, ctrl-c or alt-. on other systems) or when the low-space watcher detects that memory is low."
  30871.  
  30872.     | debugger |
  30873.     debugger _ self new.
  30874.     debugger
  30875.         process: interruptedProcess
  30876.         controller: (ScheduledControllers activeControllerProcess == interruptedProcess
  30877.                         ifTrue: [ScheduledControllers activeController])
  30878.         context: interruptedProcess suspendedContext.
  30879.     debugger externalInterrupt: true.
  30880.     ^ debugger
  30881.         openNotifierContents: debugger interruptedContext shortStack
  30882.         label: aString
  30883. ! !
  30884. InstructionStream subclass: #Decompiler
  30885.     instanceVariableNames: 'constructor method instVars tempVars constTable stack statements lastPc exit lastJumpPc lastReturnPc limit hasValue blockStackBase '
  30886.     classVariableNames: 'ArgumentFlag CascadeFlag CaseFlag '
  30887.     poolDictionaries: ''
  30888.     category: 'System-Compiler'!
  30889. !Decompiler commentStamp: 'di 5/22/1998 16:33' prior: 0!
  30890. Decompiler comment:
  30891. 'I decompile a method in three phases:
  30892.     Reverser: postfix byte codes -> prefix symbolic codes (nodes and atoms)
  30893.     Parser: prefix symbolic codes -> node tree (same as the compiler)
  30894.     Printer: node tree -> text (done by the nodes)'!
  30895.  
  30896.  
  30897. !Decompiler methodsFor: 'initialize-release'!
  30898. initSymbols: aClass
  30899.     | nTemps namedTemps |
  30900.     constructor method: method class: aClass literals: method literals.
  30901.     constTable _ constructor codeConstants.
  30902.     instVars _ Array new: aClass instSize.
  30903.     nTemps _ method numTemps.
  30904.     namedTemps _ tempVars == nil ifTrue: [Array new] ifFalse: [tempVars].
  30905.     tempVars _ (1 to: nTemps) collect:
  30906.                 [:i | i <= namedTemps size
  30907.                     ifTrue: [constructor codeTemp: i - 1 named: (namedTemps at: i)]
  30908.                     ifFalse: [constructor codeTemp: i - 1]]! !
  30909.  
  30910. !Decompiler methodsFor: 'initialize-release'!
  30911. withTempNames: tempNameArray
  30912.     tempVars _ tempNameArray! !
  30913.  
  30914.  
  30915. !Decompiler methodsFor: 'control' stamp: 'tao 8/20/97 22:51'!
  30916. blockForCaseTo: end
  30917.     "Decompile a range of code as in statementsForCaseTo:, but return a block node."
  30918.     | exprs block oldBase |
  30919.     oldBase _ blockStackBase.
  30920.     blockStackBase _ stack size.
  30921.     exprs _ self statementsForCaseTo: end.
  30922.     block _ constructor codeBlock: exprs returns: lastReturnPc = lastPc.
  30923.     blockStackBase _ oldBase.
  30924.     lastReturnPc _ -1.  "So as not to mislead outer calls"
  30925.     ^block! !
  30926.  
  30927. !Decompiler methodsFor: 'control'!
  30928. blockTo: end
  30929.     "Decompile a range of code as in statementsTo:, but return a block node."
  30930.     | exprs block oldBase |
  30931.     oldBase _ blockStackBase.
  30932.     blockStackBase _ stack size.
  30933.     exprs _ self statementsTo: end.
  30934.     block _ constructor codeBlock: exprs returns: lastReturnPc = lastPc.
  30935.     blockStackBase _ oldBase.
  30936.     lastReturnPc _ -1.  "So as not to mislead outer calls"
  30937.     ^block! !
  30938.  
  30939. !Decompiler methodsFor: 'control'!
  30940. checkForBlock: receiver
  30941.     "We just saw a blockCopy: message. Check for a following block."
  30942.  
  30943.     | savePc jump args argPos block |
  30944.     receiver == constructor codeThisContext ifFalse: [^false].
  30945.     savePc _ pc.
  30946.     (jump _ self interpretJump) notNil
  30947.         ifFalse:
  30948.             [pc _ savePc.  ^nil].
  30949.     "Definitely a block"
  30950.     jump _ jump + pc.
  30951.     argPos _ statements size.
  30952.     [self willStorePop]
  30953.         whileTrue:
  30954.             [stack addLast: ArgumentFlag.  "Flag for doStore:"
  30955.             self interpretNextInstructionFor: self].
  30956.     args _ Array new: statements size - argPos.
  30957.     1 to: args size do:  "Retrieve args"
  30958.         [:i | args at: i put: statements removeLast.
  30959.         (args at: i) scope: -1  "flag args as block temps"].
  30960.     block _ self blockTo: jump.
  30961.     stack addLast: (constructor codeArguments: args block: block).
  30962.     ^true! !
  30963.  
  30964. !Decompiler methodsFor: 'control' stamp: 'tao 8/20/97 22:51'!
  30965. statementsForCaseTo: end
  30966.     "Decompile the method from pc up to end and return an array of
  30967.     expressions. If at run time this block will leave a value on the stack,
  30968.     set hasValue to true. If the block ends with a jump or return, set exit
  30969.     to the destination of the jump, or the end of the method; otherwise, set
  30970.     exit = end. Leave pc = end.
  30971.     Note that stack initially contains a CaseFlag which will be removed by
  30972.     a subsequent Pop instruction, so adjust the StackPos accordingly."
  30973.  
  30974.     | blockPos stackPos t |
  30975.     blockPos _ statements size.
  30976.     stackPos _ stack size - 1. "Adjust for CaseFlag"
  30977.     [pc < end]
  30978.         whileTrue:
  30979.             [lastPc _ pc.  limit _ end.  "for performs"
  30980.             self interpretNextInstructionFor: self].
  30981.     "If there is an additional item on the stack, it will be the value
  30982.     of this block."
  30983.     (hasValue _ stack size > stackPos)
  30984.         ifTrue:
  30985.             [statements addLast: stack removeLast].
  30986.     lastJumpPc = lastPc ifFalse: [exit _ pc].
  30987.     ^self popTo: blockPos! !
  30988.  
  30989. !Decompiler methodsFor: 'control'!
  30990. statementsTo: end
  30991.     "Decompile the method from pc up to end and return an array of
  30992.     expressions. If at run time this block will leave a value on the stack,
  30993.     set hasValue to true. If the block ends with a jump or return, set exit
  30994.     to the destination of the jump, or the end of the method; otherwise, set
  30995.     exit = end. Leave pc = end."
  30996.  
  30997.     | blockPos stackPos t |
  30998.     blockPos _ statements size.
  30999.     stackPos _ stack size.
  31000.     [pc < end]
  31001.         whileTrue:
  31002.             [lastPc _ pc.  limit _ end.  "for performs"
  31003.             self interpretNextInstructionFor: self].
  31004.     "If there is an additional item on the stack, it will be the value
  31005.     of this block."
  31006.     (hasValue _ stack size > stackPos)
  31007.         ifTrue:
  31008.             [statements addLast: stack removeLast].
  31009.     lastJumpPc = lastPc ifFalse: [exit _ pc].
  31010.     ^self popTo: blockPos! !
  31011.  
  31012.  
  31013. !Decompiler methodsFor: 'instruction decoding'!
  31014. blockReturnTop
  31015.     "No action needed"! !
  31016.  
  31017. !Decompiler methodsFor: 'instruction decoding' stamp: 'tao 8/20/97 22:49'!
  31018. case: dist
  31019.     "statements = keyStmts CascadeFlag keyValueBlock ... keyStmts"
  31020.  
  31021.     | nextCase end thenJump stmtStream elements b node cases otherBlock |
  31022.     nextCase _ pc + dist.
  31023.     end _ limit.
  31024.     "Now add CascadeFlag & keyValueBlock to statements"
  31025.     statements addLast: stack removeLast.
  31026.     stack addLast: CaseFlag. "set for next pop"
  31027.     statements addLast: (self blockForCaseTo: nextCase).
  31028.     stack last == CaseFlag
  31029.         ifTrue: "Last case"
  31030.             ["ensure jump is within block (in case thenExpr returns wierdly I guess)"
  31031.             stack removeLast. "get rid of CaseFlag".
  31032.             thenJump _ exit <= end ifTrue: [exit] ifFalse: [nextCase].
  31033.             stmtStream _ ReadStream on: (self popTo: stack removeLast).
  31034.             elements _ OrderedCollection new.
  31035.             b _ OrderedCollection new.
  31036.             [stmtStream atEnd] whileFalse:
  31037.                 [(node _ stmtStream next) == CascadeFlag
  31038.                     ifTrue:
  31039.                         [elements addLast: (constructor
  31040.                             codeMessage: (constructor codeBlock: b returns: false)
  31041.                             selector: (constructor codeSelector: #-> code: #macro)
  31042.                             arguments: (Array with: stmtStream next)).
  31043.                          b _ OrderedCollection new]
  31044.                     ifFalse: [b addLast: node]].
  31045.             b size > 0 ifTrue: [self error: 'Bad cases'].
  31046.             cases _ constructor codeBrace: elements.
  31047.             otherBlock _ self blockTo: thenJump.
  31048.             stack addLast:
  31049.                 (constructor
  31050.                     codeMessage: stack removeLast
  31051.                     selector: (constructor codeSelector: #caseOf:otherwise: code: #macro)
  31052.                     arguments: (Array with: cases with: otherBlock))]! !
  31053.  
  31054. !Decompiler methodsFor: 'instruction decoding'!
  31055. doDup
  31056.  
  31057.     stack last == CascadeFlag
  31058.         ifFalse:
  31059.             ["Save position and mark cascade"
  31060.             stack addLast: statements size.
  31061.             stack addLast: CascadeFlag].
  31062.     stack addLast: CascadeFlag! !
  31063.  
  31064. !Decompiler methodsFor: 'instruction decoding' stamp: 'tao 8/20/97 22:54'!
  31065. doPop
  31066.  
  31067.     stack last == CaseFlag
  31068.         ifTrue: [stack removeLast]
  31069.         ifFalse: [statements addLast: stack removeLast].! !
  31070.  
  31071. !Decompiler methodsFor: 'instruction decoding'!
  31072. doStore: stackOrBlock
  31073.     "Only called internally, not from InstructionStream. StackOrBlock is stack
  31074.     for store, statements for storePop."
  31075.  
  31076.     | var expr |
  31077.     var _ stack removeLast.
  31078.     expr _ stack removeLast.
  31079.     stackOrBlock addLast: (expr == ArgumentFlag
  31080.         ifTrue: [var]
  31081.         ifFalse: [constructor codeAssignTo: var value: expr])! !
  31082.  
  31083. !Decompiler methodsFor: 'instruction decoding'!
  31084. jump: dist
  31085.  
  31086.     exit _ pc + dist.
  31087.     lastJumpPc _ lastPc! !
  31088.  
  31089. !Decompiler methodsFor: 'instruction decoding'!
  31090. jump: dist if: condition
  31091.  
  31092.     | savePc elseDist sign elsePc elseStart end cond ifExpr thenBlock elseBlock thenJump
  31093.         elseJump condHasValue b |
  31094.     stack last == CascadeFlag ifTrue: [^self case: dist].
  31095.     elsePc _ lastPc.
  31096.     elseStart _ pc + dist.
  31097.     end _ limit.
  31098.     "Check for bfp-jmp to invert condition.
  31099.     Don't be fooled by a loop with a null body."
  31100.     sign _ condition.
  31101.     savePc _ pc.
  31102.     ((elseDist _ self interpretJump) notNil and: [elseDist >= 0 and: [elseStart = pc]])
  31103.         ifTrue: [sign _ sign not.  elseStart _ pc + elseDist]
  31104.         ifFalse: [pc _ savePc].
  31105.     ifExpr _ stack removeLast.
  31106.     thenBlock _ self blockTo: elseStart.
  31107.     condHasValue _ hasValue.
  31108.     "ensure jump is within block (in case thenExpr returns)"
  31109.     thenJump _ exit <= end ifTrue: [exit] ifFalse: [elseStart].
  31110.     "if jump goes back, then it's a loop"
  31111.     thenJump < elseStart
  31112.         ifTrue:
  31113.             ["thenJump will jump to the beginning of the while expr.  In the case of
  31114.             while's with a block in the condition, the while expr
  31115.             should include more than just the last expression: find all the
  31116.             statements needed by re-decompiling."
  31117.             pc _ thenJump.
  31118.             b _ self statementsTo: elsePc.
  31119.             "discard unwanted statements from block"
  31120.             b size - 1 timesRepeat: [statements removeLast].
  31121.             statements addLast: (constructor
  31122.                     codeMessage: (constructor codeBlock: b returns: false)
  31123.                     selector: (constructor codeSelector: (sign ifTrue: [#whileFalse:] ifFalse: [#whileTrue:]) code: #macro)
  31124.                     arguments: (Array with: thenBlock)).
  31125.             pc _ elseStart.
  31126.             self convertToDoLoop]
  31127.         ifFalse:
  31128.             [elseBlock _ self blockTo: thenJump.
  31129.             elseJump _ exit.
  31130.             "if elseJump is backwards, it is not part of the elseExpr"
  31131.             elseJump < elsePc
  31132.                 ifTrue: [pc _ lastPc].
  31133.             cond _ constructor
  31134.                         codeMessage: ifExpr
  31135.                         selector: (constructor codeSelector: #ifTrue:ifFalse: code: #macro)
  31136.                         arguments:
  31137.                             (sign
  31138.                                 ifTrue: [Array with: elseBlock with: thenBlock]
  31139.                                 ifFalse: [Array with: thenBlock with: elseBlock]).
  31140.             condHasValue
  31141.                 ifTrue: [stack addLast: cond]
  31142.                 ifFalse: [statements addLast: cond]]! !
  31143.  
  31144. !Decompiler methodsFor: 'instruction decoding'!
  31145. methodReturnConstant: value
  31146.  
  31147.     self pushConstant: value; methodReturnTop! !
  31148.  
  31149. !Decompiler methodsFor: 'instruction decoding'!
  31150. methodReturnReceiver
  31151.  
  31152.     self pushReceiver; methodReturnTop! !
  31153.  
  31154. !Decompiler methodsFor: 'instruction decoding'!
  31155. methodReturnTop
  31156.     | last |
  31157.     last _ stack removeLast.
  31158.     stack size > blockStackBase  "get effect of elided pop before return"
  31159.         ifTrue: [statements addLast: stack removeLast].
  31160.     exit _ method size + 1.
  31161.     lastJumpPc _ lastReturnPc _ lastPc.
  31162.     statements addLast: last! !
  31163.  
  31164. !Decompiler methodsFor: 'instruction decoding'!
  31165. popIntoLiteralVariable: value
  31166.  
  31167.     self pushLiteralVariable: value; doStore: statements! !
  31168.  
  31169. !Decompiler methodsFor: 'instruction decoding'!
  31170. popIntoReceiverVariable: offset
  31171.  
  31172.     self pushReceiverVariable: offset; doStore: statements! !
  31173.  
  31174. !Decompiler methodsFor: 'instruction decoding'!
  31175. popIntoTemporaryVariable: offset
  31176.  
  31177.     self pushTemporaryVariable: offset; doStore: statements! !
  31178.  
  31179. !Decompiler methodsFor: 'instruction decoding'!
  31180. pushActiveContext
  31181.  
  31182.     stack addLast: constructor codeThisContext! !
  31183.  
  31184. !Decompiler methodsFor: 'instruction decoding'!
  31185. pushConstant: value
  31186.  
  31187.     | node |
  31188.     node _ value == true ifTrue: [constTable at: 2]
  31189.         ifFalse: [value == false ifTrue: [constTable at: 3]
  31190.         ifFalse: [value == nil ifTrue: [constTable at: 4]
  31191.         ifFalse: [constructor codeAnyLiteral: value]]].
  31192.     stack addLast: node! !
  31193.  
  31194. !Decompiler methodsFor: 'instruction decoding'!
  31195. pushLiteralVariable: assoc
  31196.  
  31197.     stack addLast: (constructor codeAnyLitInd: assoc)! !
  31198.  
  31199. !Decompiler methodsFor: 'instruction decoding'!
  31200. pushReceiver
  31201.  
  31202.     stack addLast: (constTable at: 1)! !
  31203.  
  31204. !Decompiler methodsFor: 'instruction decoding'!
  31205. pushReceiverVariable: offset
  31206.  
  31207.     | var |
  31208.     (var _ instVars at: offset + 1) == nil
  31209.         ifTrue:
  31210.             ["Not set up yet"